From 8a81eb263442221da3cbf203751789f0548cd7cb Mon Sep 17 00:00:00 2001 From: urania Date: Mon, 22 Jun 2026 17:47:16 +0200 Subject: [PATCH] initial commit --- .env.example | 2 + .gitignore | 28 + .npmrc | 1 + .prettierignore | 10 + .prettierrc | 16 + .vscode/extensions.json | 8 + .vscode/settings.json | 6 + README.md | 119 + bun.lock | 1376 ++++ components.json | 20 + config/oauth.json | 1 + db.sqlite | Bin 0 -> 94208 bytes drizzle.config.ts | 11 + .../20260621092126_real_klaw/migration.sql | 70 + .../20260621092126_real_klaw/snapshot.json | 688 ++ .../migration.sql | 8 + .../snapshot.json | 770 ++ .../migration.sql | 3 + .../snapshot.json | 760 ++ eslint.config.js | 42 + messages/en.json | 271 + package.json | 80 + project.inlang/settings.json | 12 + src/app.d.ts | 23 + src/app.html | 20 + src/hooks.server.ts | 58 + src/hooks.ts | 5 + src/lib/assets/favicon.svg | 9 + src/lib/auth/client.ts | 31 + src/lib/auth/schemas.ts | 93 + src/lib/auth/server.ts | 106 + src/lib/components/blocks/app-controls.svelte | 92 + .../blocks/breadcrumbs/breadcrumbs.svelte | 49 + .../blocks/sidebar/app-sidebar.svelte | 234 + .../blocks/sidebar/machines-nav.svelte | 184 + .../components/blocks/sidebar/nav-user.svelte | 82 + src/lib/components/blocks/trunk/trunk.svelte | 202 + .../dashboard/activity-panel.svelte | 45 + .../components/dashboard/cpu-heatmap.svelte | 112 + .../components/dashboard/data-panel.svelte | 138 + src/lib/components/dashboard/format.ts | 61 + src/lib/components/dashboard/kpi-card.svelte | 39 + .../components/dashboard/network-panel.svelte | 45 + .../components/dashboard/storage-panel.svelte | 45 + .../components/dashboard/system-panel.svelte | 117 + .../dashboard/temperature-panel.svelte | 38 + src/lib/components/dashboard/types.ts | 33 + .../ui/accordion/accordion-content.svelte | 27 + .../ui/accordion/accordion-item.svelte | 17 + .../ui/accordion/accordion-trigger.svelte | 38 + .../components/ui/accordion/accordion.svelte | 19 + src/lib/components/ui/accordion/index.ts | 16 + .../alert-dialog/alert-dialog-action.svelte | 27 + .../alert-dialog/alert-dialog-cancel.svelte | 27 + .../alert-dialog/alert-dialog-content.svelte | 34 + .../alert-dialog-description.svelte | 20 + .../alert-dialog/alert-dialog-footer.svelte | 24 + .../alert-dialog/alert-dialog-header.svelte | 24 + .../ui/alert-dialog/alert-dialog-media.svelte | 24 + .../alert-dialog/alert-dialog-overlay.svelte | 20 + .../alert-dialog/alert-dialog-portal.svelte | 7 + .../ui/alert-dialog/alert-dialog-title.svelte | 20 + .../alert-dialog/alert-dialog-trigger.svelte | 7 + .../ui/alert-dialog/alert-dialog.svelte | 7 + src/lib/components/ui/alert-dialog/index.ts | 40 + .../components/ui/alert/alert-action.svelte | 21 + .../ui/alert/alert-description.svelte | 24 + .../components/ui/alert/alert-title.svelte | 24 + src/lib/components/ui/alert/alert.svelte | 45 + src/lib/components/ui/alert/index.ts | 17 + .../ui/aspect-ratio/aspect-ratio.svelte | 7 + src/lib/components/ui/aspect-ratio/index.ts | 3 + .../components/ui/avatar/avatar-badge.svelte | 27 + .../ui/avatar/avatar-fallback.svelte | 20 + .../ui/avatar/avatar-group-count.svelte | 24 + .../components/ui/avatar/avatar-group.svelte | 24 + .../components/ui/avatar/avatar-image.svelte | 17 + src/lib/components/ui/avatar/avatar.svelte | 26 + src/lib/components/ui/avatar/index.ts | 22 + src/lib/components/ui/badge/badge.svelte | 51 + src/lib/components/ui/badge/index.ts | 2 + .../ui/breadcrumb/breadcrumb-ellipsis.svelte | 24 + .../ui/breadcrumb/breadcrumb-item.svelte | 21 + .../ui/breadcrumb/breadcrumb-link.svelte | 32 + .../ui/breadcrumb/breadcrumb-list.svelte | 24 + .../ui/breadcrumb/breadcrumb-page.svelte | 24 + .../ui/breadcrumb/breadcrumb-separator.svelte | 28 + .../ui/breadcrumb/breadcrumb.svelte | 23 + src/lib/components/ui/breadcrumb/index.ts | 25 + .../button-group-separator.svelte | 24 + .../ui/button-group/button-group-text.svelte | 32 + .../ui/button-group/button-group.svelte | 47 + src/lib/components/ui/button-group/index.ts | 15 + src/lib/components/ui/button/button.svelte | 92 + src/lib/components/ui/button/index.ts | 17 + .../ui/calendar/calendar-caption.svelte | 79 + .../ui/calendar/calendar-cell.svelte | 19 + .../ui/calendar/calendar-day.svelte | 33 + .../ui/calendar/calendar-grid-body.svelte | 12 + .../ui/calendar/calendar-grid-head.svelte | 12 + .../ui/calendar/calendar-grid-row.svelte | 12 + .../ui/calendar/calendar-grid.svelte | 16 + .../ui/calendar/calendar-head-cell.svelte | 19 + .../ui/calendar/calendar-header.svelte | 19 + .../ui/calendar/calendar-heading.svelte | 16 + .../ui/calendar/calendar-month-select.svelte | 48 + .../ui/calendar/calendar-month.svelte | 16 + .../ui/calendar/calendar-months.svelte | 20 + .../ui/calendar/calendar-nav.svelte | 20 + .../ui/calendar/calendar-next-button.svelte | 36 + .../ui/calendar/calendar-prev-button.svelte | 36 + .../ui/calendar/calendar-year-select.svelte | 47 + .../components/ui/calendar/calendar.svelte | 118 + src/lib/components/ui/calendar/index.ts | 40 + src/lib/components/ui/card/card-action.svelte | 24 + .../components/ui/card/card-content.svelte | 21 + .../ui/card/card-description.svelte | 21 + src/lib/components/ui/card/card-footer.svelte | 24 + src/lib/components/ui/card/card-header.svelte | 24 + src/lib/components/ui/card/card-title.svelte | 21 + src/lib/components/ui/card/card.svelte | 26 + src/lib/components/ui/card/index.ts | 25 + .../ui/carousel/carousel-content.svelte | 45 + .../ui/carousel/carousel-item.svelte | 32 + .../ui/carousel/carousel-next.svelte | 41 + .../ui/carousel/carousel-previous.svelte | 41 + .../components/ui/carousel/carousel.svelte | 95 + src/lib/components/ui/carousel/context.ts | 59 + src/lib/components/ui/carousel/index.ts | 19 + .../ui/chart/chart-container.svelte | 82 + .../components/ui/chart/chart-style.svelte | 37 + .../components/ui/chart/chart-tooltip.svelte | 183 + src/lib/components/ui/chart/chart-utils.ts | 69 + src/lib/components/ui/chart/index.ts | 6 + .../components/ui/checkbox/checkbox.svelte | 39 + src/lib/components/ui/checkbox/index.ts | 6 + .../ui/collapsible/collapsible-content.svelte | 7 + .../ui/collapsible/collapsible-trigger.svelte | 7 + .../ui/collapsible/collapsible.svelte | 11 + src/lib/components/ui/collapsible/index.ts | 13 + .../ui/command/command-dialog.svelte | 44 + .../ui/command/command-empty.svelte | 17 + .../ui/command/command-group.svelte | 33 + .../ui/command/command-input.svelte | 36 + .../components/ui/command/command-item.svelte | 27 + .../ui/command/command-link-item.svelte | 20 + .../components/ui/command/command-list.svelte | 20 + .../ui/command/command-loading.svelte | 7 + .../ui/command/command-separator.svelte | 17 + .../ui/command/command-shortcut.svelte | 24 + src/lib/components/ui/command/command.svelte | 28 + src/lib/components/ui/command/index.ts | 37 + .../context-menu-checkbox-item.svelte | 42 + .../context-menu/context-menu-content.svelte | 30 + .../context-menu-group-heading.svelte | 21 + .../ui/context-menu/context-menu-group.svelte | 7 + .../ui/context-menu/context-menu-item.svelte | 27 + .../ui/context-menu/context-menu-label.svelte | 28 + .../context-menu/context-menu-portal.svelte | 7 + .../context-menu-radio-group.svelte | 16 + .../context-menu-radio-item.svelte | 35 + .../context-menu-separator.svelte | 17 + .../context-menu/context-menu-shortcut.svelte | 24 + .../context-menu-sub-content.svelte | 20 + .../context-menu-sub-trigger.svelte | 29 + .../ui/context-menu/context-menu-sub.svelte | 7 + .../context-menu/context-menu-trigger.svelte | 17 + .../ui/context-menu/context-menu.svelte | 7 + src/lib/components/ui/context-menu/index.ts | 52 + .../ui/data-table/data-table.svelte.ts | 142 + .../ui/data-table/flex-render.svelte | 41 + src/lib/components/ui/data-table/index.ts | 3 + .../ui/data-table/render-helpers.ts | 111 + .../components/ui/dialog/dialog-close.svelte | 11 + .../ui/dialog/dialog-content.svelte | 50 + .../ui/dialog/dialog-description.svelte | 20 + .../components/ui/dialog/dialog-footer.svelte | 36 + .../components/ui/dialog/dialog-header.svelte | 21 + .../ui/dialog/dialog-overlay.svelte | 20 + .../components/ui/dialog/dialog-portal.svelte | 7 + .../components/ui/dialog/dialog-title.svelte | 17 + .../ui/dialog/dialog-trigger.svelte | 11 + src/lib/components/ui/dialog/dialog.svelte | 7 + src/lib/components/ui/dialog/index.ts | 34 + .../components/ui/drawer/drawer-close.svelte | 7 + .../ui/drawer/drawer-content.svelte | 38 + .../ui/drawer/drawer-description.svelte | 17 + .../components/ui/drawer/drawer-footer.svelte | 21 + .../components/ui/drawer/drawer-header.svelte | 24 + .../components/ui/drawer/drawer-nested.svelte | 12 + .../ui/drawer/drawer-overlay.svelte | 20 + .../components/ui/drawer/drawer-portal.svelte | 7 + .../components/ui/drawer/drawer-title.svelte | 17 + .../ui/drawer/drawer-trigger.svelte | 7 + src/lib/components/ui/drawer/drawer.svelte | 12 + src/lib/components/ui/drawer/index.ts | 37 + .../dropdown-menu-checkbox-group.svelte | 16 + .../dropdown-menu-checkbox-item.svelte | 45 + .../dropdown-menu-content.svelte | 33 + .../dropdown-menu-group-heading.svelte | 23 + .../dropdown-menu/dropdown-menu-group.svelte | 7 + .../dropdown-menu/dropdown-menu-item.svelte | 27 + .../dropdown-menu/dropdown-menu-label.svelte | 28 + .../dropdown-menu/dropdown-menu-portal.svelte | 7 + .../dropdown-menu-radio-group.svelte | 16 + .../dropdown-menu-radio-item.svelte | 34 + .../dropdown-menu-separator.svelte | 17 + .../dropdown-menu-shortcut.svelte | 24 + .../dropdown-menu-sub-content.svelte | 20 + .../dropdown-menu-sub-trigger.svelte | 29 + .../ui/dropdown-menu/dropdown-menu-sub.svelte | 7 + .../dropdown-menu-trigger.svelte | 7 + .../ui/dropdown-menu/dropdown-menu.svelte | 7 + src/lib/components/ui/dropdown-menu/index.ts | 54 + .../components/ui/empty/empty-content.svelte | 24 + .../ui/empty/empty-description.svelte | 24 + .../components/ui/empty/empty-header.svelte | 21 + .../components/ui/empty/empty-media.svelte | 42 + .../components/ui/empty/empty-title.svelte | 21 + src/lib/components/ui/empty/empty.svelte | 24 + src/lib/components/ui/empty/index.ts | 22 + .../components/ui/field/field-content.svelte | 21 + .../ui/field/field-description.svelte | 26 + .../components/ui/field/field-error.svelte | 59 + .../components/ui/field/field-group.svelte | 24 + .../components/ui/field/field-label.svelte | 26 + .../components/ui/field/field-legend.svelte | 28 + .../ui/field/field-separator.svelte | 36 + src/lib/components/ui/field/field-set.svelte | 24 + .../components/ui/field/field-title.svelte | 24 + src/lib/components/ui/field/field.svelte | 48 + src/lib/components/ui/field/index.ts | 33 + src/lib/components/ui/form/form-button.svelte | 7 + .../ui/form/form-description.svelte | 17 + .../ui/form/form-element-field.svelte | 25 + .../ui/form/form-field-errors.svelte | 30 + src/lib/components/ui/form/form-field.svelte | 25 + .../components/ui/form/form-fieldset.svelte | 16 + src/lib/components/ui/form/form-label.svelte | 24 + src/lib/components/ui/form/form-legend.svelte | 16 + src/lib/components/ui/form/index.ts | 34 + .../ui/hover-card/hover-card-content.svelte | 33 + .../ui/hover-card/hover-card-portal.svelte | 7 + .../ui/hover-card/hover-card-trigger.svelte | 7 + .../ui/hover-card/hover-card.svelte | 7 + src/lib/components/ui/hover-card/index.ts | 15 + src/lib/components/ui/input-group/index.ts | 22 + .../ui/input-group/input-group-addon.svelte | 54 + .../ui/input-group/input-group-button.svelte | 50 + .../ui/input-group/input-group-input.svelte | 24 + .../ui/input-group/input-group-text.svelte | 23 + .../input-group/input-group-textarea.svelte | 24 + .../ui/input-group/input-group.svelte | 25 + src/lib/components/ui/input-otp/index.ts | 15 + .../ui/input-otp/input-otp-group.svelte | 24 + .../ui/input-otp/input-otp-separator.svelte | 28 + .../ui/input-otp/input-otp-slot.svelte | 31 + .../components/ui/input-otp/input-otp.svelte | 23 + src/lib/components/ui/input/index.ts | 7 + src/lib/components/ui/input/input.svelte | 49 + src/lib/components/ui/item/index.ts | 34 + .../components/ui/item/item-actions.svelte | 21 + .../components/ui/item/item-content.svelte | 24 + .../ui/item/item-description.svelte | 24 + src/lib/components/ui/item/item-footer.svelte | 21 + src/lib/components/ui/item/item-group.svelte | 25 + src/lib/components/ui/item/item-header.svelte | 21 + src/lib/components/ui/item/item-media.svelte | 44 + .../components/ui/item/item-separator.svelte | 20 + src/lib/components/ui/item/item-title.svelte | 24 + src/lib/components/ui/item/item.svelte | 62 + src/lib/components/ui/kbd/index.ts | 10 + src/lib/components/ui/kbd/kbd-group.svelte | 21 + src/lib/components/ui/kbd/kbd.svelte | 24 + src/lib/components/ui/label/index.ts | 7 + src/lib/components/ui/label/label.svelte | 20 + src/lib/components/ui/menubar/index.ts | 55 + .../ui/menubar/menubar-checkbox-item.svelte | 47 + .../ui/menubar/menubar-content.svelte | 37 + .../ui/menubar/menubar-group-heading.svelte | 23 + .../ui/menubar/menubar-group.svelte | 12 + .../components/ui/menubar/menubar-item.svelte | 27 + .../ui/menubar/menubar-label.svelte | 26 + .../components/ui/menubar/menubar-menu.svelte | 7 + .../ui/menubar/menubar-portal.svelte | 7 + .../ui/menubar/menubar-radio-group.svelte | 11 + .../ui/menubar/menubar-radio-item.svelte | 37 + .../ui/menubar/menubar-separator.svelte | 17 + .../ui/menubar/menubar-shortcut.svelte | 24 + .../ui/menubar/menubar-sub-content.svelte | 20 + .../ui/menubar/menubar-sub-trigger.svelte | 29 + .../components/ui/menubar/menubar-sub.svelte | 7 + .../ui/menubar/menubar-trigger.svelte | 20 + src/lib/components/ui/menubar/menubar.svelte | 17 + src/lib/components/ui/native-select/index.ts | 12 + .../native-select-opt-group.svelte | 14 + .../native-select/native-select-option.svelte | 21 + .../ui/native-select/native-select.svelte | 44 + .../components/ui/navigation-menu/index.ts | 28 + .../navigation-menu-content.svelte | 20 + .../navigation-menu-indicator.svelte | 22 + .../navigation-menu-item.svelte | 17 + .../navigation-menu-link.svelte | 20 + .../navigation-menu-list.svelte | 17 + .../navigation-menu-trigger.svelte | 32 + .../navigation-menu-viewport.svelte | 22 + .../ui/navigation-menu/navigation-menu.svelte | 32 + src/lib/components/ui/pagination/index.ts | 31 + .../ui/pagination/pagination-content.svelte | 21 + .../ui/pagination/pagination-ellipsis.svelte | 26 + .../ui/pagination/pagination-item.svelte | 14 + .../ui/pagination/pagination-link.svelte | 42 + .../pagination/pagination-next-button.svelte | 32 + .../ui/pagination/pagination-next.svelte | 22 + .../pagination/pagination-prev-button.svelte | 32 + .../ui/pagination/pagination-previous.svelte | 22 + .../ui/pagination/pagination.svelte | 27 + src/lib/components/ui/popover/index.ts | 28 + .../ui/popover/popover-close.svelte | 7 + .../ui/popover/popover-content.svelte | 33 + .../ui/popover/popover-description.svelte | 21 + .../ui/popover/popover-header.svelte | 21 + .../ui/popover/popover-portal.svelte | 7 + .../ui/popover/popover-title.svelte | 16 + .../ui/popover/popover-trigger.svelte | 17 + src/lib/components/ui/popover/popover.svelte | 7 + src/lib/components/ui/progress/index.ts | 7 + .../components/ui/progress/progress.svelte | 30 + src/lib/components/ui/radio-group/index.ts | 10 + .../ui/radio-group/radio-group-item.svelte | 31 + .../ui/radio-group/radio-group.svelte | 19 + src/lib/components/ui/range-calendar/index.ts | 40 + .../range-calendar-caption.svelte | 79 + .../range-calendar/range-calendar-cell.svelte | 19 + .../range-calendar/range-calendar-day.svelte | 36 + .../range-calendar-grid-body.svelte | 7 + .../range-calendar-grid-head.svelte | 7 + .../range-calendar-grid-row.svelte | 12 + .../range-calendar/range-calendar-grid.svelte | 16 + .../range-calendar-head-cell.svelte | 19 + .../range-calendar-header.svelte | 19 + .../range-calendar-heading.svelte | 16 + .../range-calendar-month-select.svelte | 44 + .../range-calendar-month.svelte | 16 + .../range-calendar-months.svelte | 20 + .../range-calendar/range-calendar-nav.svelte | 20 + .../range-calendar-next-button.svelte | 36 + .../range-calendar-prev-button.svelte | 36 + .../range-calendar-year-select.svelte | 43 + .../ui/range-calendar/range-calendar.svelte | 114 + src/lib/components/ui/resizable/index.ts | 14 + .../ui/resizable/resizable-handle.svelte | 27 + .../ui/resizable/resizable-pane-group.svelte | 24 + src/lib/components/ui/scroll-area/index.ts | 10 + .../scroll-area/scroll-area-scrollbar.svelte | 30 + .../ui/scroll-area/scroll-area.svelte | 44 + src/lib/components/ui/select/index.ts | 37 + .../ui/select/select-content.svelte | 47 + .../ui/select/select-group-heading.svelte | 22 + .../components/ui/select/select-group.svelte | 17 + .../components/ui/select/select-item.svelte | 40 + .../components/ui/select/select-label.svelte | 21 + .../components/ui/select/select-portal.svelte | 7 + .../select/select-scroll-down-button.svelte | 23 + .../ui/select/select-scroll-up-button.svelte | 23 + .../ui/select/select-separator.svelte | 19 + .../ui/select/select-trigger.svelte | 29 + src/lib/components/ui/select/select.svelte | 11 + src/lib/components/ui/separator/index.ts | 7 + .../components/ui/separator/separator.svelte | 23 + src/lib/components/ui/sheet/index.ts | 34 + .../components/ui/sheet/sheet-close.svelte | 7 + .../components/ui/sheet/sheet-content.svelte | 57 + .../ui/sheet/sheet-description.svelte | 17 + .../components/ui/sheet/sheet-footer.svelte | 21 + .../components/ui/sheet/sheet-header.svelte | 21 + .../components/ui/sheet/sheet-overlay.svelte | 17 + .../components/ui/sheet/sheet-portal.svelte | 7 + .../components/ui/sheet/sheet-title.svelte | 17 + .../components/ui/sheet/sheet-trigger.svelte | 7 + src/lib/components/ui/sheet/sheet.svelte | 7 + src/lib/components/ui/sidebar/constants.ts | 6 + .../components/ui/sidebar/context.svelte.ts | 80 + src/lib/components/ui/sidebar/index.ts | 75 + .../ui/sidebar/sidebar-content.svelte | 25 + .../ui/sidebar/sidebar-footer.svelte | 22 + .../ui/sidebar/sidebar-group-action.svelte | 34 + .../ui/sidebar/sidebar-group-content.svelte | 22 + .../ui/sidebar/sidebar-group-label.svelte | 34 + .../ui/sidebar/sidebar-group.svelte | 22 + .../ui/sidebar/sidebar-header.svelte | 22 + .../ui/sidebar/sidebar-input.svelte | 22 + .../ui/sidebar/sidebar-inset.svelte | 24 + .../ui/sidebar/sidebar-menu-action.svelte | 38 + .../ui/sidebar/sidebar-menu-badge.svelte | 25 + .../ui/sidebar/sidebar-menu-button.svelte | 103 + .../ui/sidebar/sidebar-menu-item.svelte | 22 + .../ui/sidebar/sidebar-menu-skeleton.svelte | 37 + .../ui/sidebar/sidebar-menu-sub-button.svelte | 40 + .../ui/sidebar/sidebar-menu-sub-item.svelte | 22 + .../ui/sidebar/sidebar-menu-sub.svelte | 25 + .../components/ui/sidebar/sidebar-menu.svelte | 22 + .../ui/sidebar/sidebar-provider.svelte | 55 + .../components/ui/sidebar/sidebar-rail.svelte | 38 + .../ui/sidebar/sidebar-separator.svelte | 20 + .../ui/sidebar/sidebar-trigger.svelte | 38 + src/lib/components/ui/sidebar/sidebar.svelte | 107 + src/lib/components/ui/skeleton/index.ts | 7 + .../components/ui/skeleton/skeleton.svelte | 18 + src/lib/components/ui/slider/index.ts | 7 + src/lib/components/ui/slider/slider.svelte | 50 + src/lib/components/ui/sonner/index.ts | 1 + src/lib/components/ui/sonner/sonner.svelte | 34 + src/lib/components/ui/spinner/index.ts | 1 + src/lib/components/ui/spinner/spinner.svelte | 27 + src/lib/components/ui/switch/index.ts | 7 + src/lib/components/ui/switch/switch.svelte | 31 + src/lib/components/ui/table/index.ts | 28 + src/lib/components/ui/table/table-body.svelte | 21 + .../components/ui/table/table-caption.svelte | 21 + src/lib/components/ui/table/table-cell.svelte | 21 + .../components/ui/table/table-footer.svelte | 21 + src/lib/components/ui/table/table-head.svelte | 24 + .../components/ui/table/table-header.svelte | 21 + src/lib/components/ui/table/table-row.svelte | 24 + src/lib/components/ui/table/table.svelte | 23 + src/lib/components/ui/tabs/index.ts | 18 + .../components/ui/tabs/tabs-content.svelte | 17 + src/lib/components/ui/tabs/tabs-list.svelte | 40 + .../components/ui/tabs/tabs-trigger.svelte | 23 + src/lib/components/ui/tabs/tabs.svelte | 19 + src/lib/components/ui/textarea/index.ts | 7 + .../components/ui/textarea/textarea.svelte | 23 + src/lib/components/ui/toggle-group/index.ts | 10 + .../ui/toggle-group/toggle-group-item.svelte | 36 + .../ui/toggle-group/toggle-group.svelte | 76 + src/lib/components/ui/toggle/index.ts | 13 + src/lib/components/ui/toggle/toggle.svelte | 52 + src/lib/components/ui/tooltip/index.ts | 19 + .../ui/tooltip/tooltip-content.svelte | 54 + .../ui/tooltip/tooltip-portal.svelte | 7 + .../ui/tooltip/tooltip-provider.svelte | 7 + .../ui/tooltip/tooltip-trigger.svelte | 7 + src/lib/components/ui/tooltip/tooltip.svelte | 7 + src/lib/const/schema.ts | 35 + src/lib/hooks/is-mobile.svelte.ts | 9 + src/lib/index.ts | 2 + src/lib/machines/schema.test.ts | 17 + src/lib/machines/schema.ts | 30 + src/lib/remotes/auth.remote.ts | 109 + src/lib/remotes/machines.remote.ts | 61 + src/lib/remotes/server.remote.ts | 97 + src/lib/remotes/users.remote.ts | 261 + src/lib/server/db/auth-schema.ts | 100 + src/lib/server/db/custom-types.ts | 65 + src/lib/server/db/index.ts | 10 + src/lib/server/db/schema.ts | 54 + .../emails/auth/complete-registration.svelte | 15 + src/lib/server/emails/auth/layout.svelte | 59 + src/lib/server/emails/auth/otp.svelte | 19 + .../server/emails/auth/reset-password.svelte | 16 + .../server/emails/auth/verify-email.svelte | 16 + src/lib/server/emails/index.ts | 71 + src/lib/server/emails/schemas.ts | 11 + src/lib/server/emails/send.ts | 29 + src/lib/server/nadir-agent/client.ts | 17 + src/lib/server/nadir-agent/schema.d.ts | 6306 +++++++++++++++++ src/lib/utils.ts | 13 + src/routes/+layout.svelte | 55 + src/routes/+page.svelte | 2 + src/routes/admin/+layout.server.ts | 3 + src/routes/admin/+page.svelte | 0 src/routes/admin/config/+page.svelte | 0 src/routes/admin/users/+page.svelte | 721 ++ src/routes/api/emailer/send/+server.ts | 23 + src/routes/auth/+layout.svelte | 23 + src/routes/auth/2fa/+page.svelte | 91 + src/routes/auth/forgot-password/+page.svelte | 62 + src/routes/auth/reset-password/+page.svelte | 72 + src/routes/auth/setup-2fa/+page.svelte | 162 + src/routes/auth/sign-in/+page.svelte | 132 + src/routes/auth/sign-up/+page.svelte | 98 + src/routes/dashboard/+page.svelte | 0 src/routes/dashboard/[machineId]/+page.svelte | 380 + src/routes/layout.css | 171 + src/routes/system/+page.svelte | 0 src/routes/system/date-time/+page.svelte | 0 src/routes/system/localization/+page.svelte | 0 static/robots.txt | 3 + tsconfig.json | 23 + vite.config.ts | 30 + 491 files changed, 26185 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 bun.lock create mode 100644 components.json create mode 100644 config/oauth.json create mode 100644 db.sqlite create mode 100644 drizzle.config.ts create mode 100644 drizzle/20260621092126_real_klaw/migration.sql create mode 100644 drizzle/20260621092126_real_klaw/snapshot.json create mode 100644 drizzle/20260621224643_moaning_logan/migration.sql create mode 100644 drizzle/20260621224643_moaning_logan/snapshot.json create mode 100644 drizzle/20260621233631_silent_otto_octavius/migration.sql create mode 100644 drizzle/20260621233631_silent_otto_octavius/snapshot.json create mode 100644 eslint.config.js create mode 100644 messages/en.json create mode 100644 package.json create mode 100644 project.inlang/settings.json create mode 100644 src/app.d.ts create mode 100644 src/app.html create mode 100644 src/hooks.server.ts create mode 100644 src/hooks.ts create mode 100644 src/lib/assets/favicon.svg create mode 100644 src/lib/auth/client.ts create mode 100644 src/lib/auth/schemas.ts create mode 100644 src/lib/auth/server.ts create mode 100644 src/lib/components/blocks/app-controls.svelte create mode 100644 src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte create mode 100644 src/lib/components/blocks/sidebar/app-sidebar.svelte create mode 100644 src/lib/components/blocks/sidebar/machines-nav.svelte create mode 100644 src/lib/components/blocks/sidebar/nav-user.svelte create mode 100644 src/lib/components/blocks/trunk/trunk.svelte create mode 100644 src/lib/components/dashboard/activity-panel.svelte create mode 100644 src/lib/components/dashboard/cpu-heatmap.svelte create mode 100644 src/lib/components/dashboard/data-panel.svelte create mode 100644 src/lib/components/dashboard/format.ts create mode 100644 src/lib/components/dashboard/kpi-card.svelte create mode 100644 src/lib/components/dashboard/network-panel.svelte create mode 100644 src/lib/components/dashboard/storage-panel.svelte create mode 100644 src/lib/components/dashboard/system-panel.svelte create mode 100644 src/lib/components/dashboard/temperature-panel.svelte create mode 100644 src/lib/components/dashboard/types.ts create mode 100644 src/lib/components/ui/accordion/accordion-content.svelte create mode 100644 src/lib/components/ui/accordion/accordion-item.svelte create mode 100644 src/lib/components/ui/accordion/accordion-trigger.svelte create mode 100644 src/lib/components/ui/accordion/accordion.svelte create mode 100644 src/lib/components/ui/accordion/index.ts create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-action.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-content.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-description.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-header.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-media.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-title.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte create mode 100644 src/lib/components/ui/alert-dialog/alert-dialog.svelte create mode 100644 src/lib/components/ui/alert-dialog/index.ts create mode 100644 src/lib/components/ui/alert/alert-action.svelte create mode 100644 src/lib/components/ui/alert/alert-description.svelte create mode 100644 src/lib/components/ui/alert/alert-title.svelte create mode 100644 src/lib/components/ui/alert/alert.svelte create mode 100644 src/lib/components/ui/alert/index.ts create mode 100644 src/lib/components/ui/aspect-ratio/aspect-ratio.svelte create mode 100644 src/lib/components/ui/aspect-ratio/index.ts create mode 100644 src/lib/components/ui/avatar/avatar-badge.svelte create mode 100644 src/lib/components/ui/avatar/avatar-fallback.svelte create mode 100644 src/lib/components/ui/avatar/avatar-group-count.svelte create mode 100644 src/lib/components/ui/avatar/avatar-group.svelte create mode 100644 src/lib/components/ui/avatar/avatar-image.svelte create mode 100644 src/lib/components/ui/avatar/avatar.svelte create mode 100644 src/lib/components/ui/avatar/index.ts create mode 100644 src/lib/components/ui/badge/badge.svelte create mode 100644 src/lib/components/ui/badge/index.ts create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-item.svelte create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-link.svelte create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-list.svelte create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-page.svelte create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte create mode 100644 src/lib/components/ui/breadcrumb/breadcrumb.svelte create mode 100644 src/lib/components/ui/breadcrumb/index.ts create mode 100644 src/lib/components/ui/button-group/button-group-separator.svelte create mode 100644 src/lib/components/ui/button-group/button-group-text.svelte create mode 100644 src/lib/components/ui/button-group/button-group.svelte create mode 100644 src/lib/components/ui/button-group/index.ts create mode 100644 src/lib/components/ui/button/button.svelte create mode 100644 src/lib/components/ui/button/index.ts create mode 100644 src/lib/components/ui/calendar/calendar-caption.svelte create mode 100644 src/lib/components/ui/calendar/calendar-cell.svelte create mode 100644 src/lib/components/ui/calendar/calendar-day.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid-body.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid-head.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid-row.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid.svelte create mode 100644 src/lib/components/ui/calendar/calendar-head-cell.svelte create mode 100644 src/lib/components/ui/calendar/calendar-header.svelte create mode 100644 src/lib/components/ui/calendar/calendar-heading.svelte create mode 100644 src/lib/components/ui/calendar/calendar-month-select.svelte create mode 100644 src/lib/components/ui/calendar/calendar-month.svelte create mode 100644 src/lib/components/ui/calendar/calendar-months.svelte create mode 100644 src/lib/components/ui/calendar/calendar-nav.svelte create mode 100644 src/lib/components/ui/calendar/calendar-next-button.svelte create mode 100644 src/lib/components/ui/calendar/calendar-prev-button.svelte create mode 100644 src/lib/components/ui/calendar/calendar-year-select.svelte create mode 100644 src/lib/components/ui/calendar/calendar.svelte create mode 100644 src/lib/components/ui/calendar/index.ts create mode 100644 src/lib/components/ui/card/card-action.svelte create mode 100644 src/lib/components/ui/card/card-content.svelte create mode 100644 src/lib/components/ui/card/card-description.svelte create mode 100644 src/lib/components/ui/card/card-footer.svelte create mode 100644 src/lib/components/ui/card/card-header.svelte create mode 100644 src/lib/components/ui/card/card-title.svelte create mode 100644 src/lib/components/ui/card/card.svelte create mode 100644 src/lib/components/ui/card/index.ts create mode 100644 src/lib/components/ui/carousel/carousel-content.svelte create mode 100644 src/lib/components/ui/carousel/carousel-item.svelte create mode 100644 src/lib/components/ui/carousel/carousel-next.svelte create mode 100644 src/lib/components/ui/carousel/carousel-previous.svelte create mode 100644 src/lib/components/ui/carousel/carousel.svelte create mode 100644 src/lib/components/ui/carousel/context.ts create mode 100644 src/lib/components/ui/carousel/index.ts create mode 100644 src/lib/components/ui/chart/chart-container.svelte create mode 100644 src/lib/components/ui/chart/chart-style.svelte create mode 100644 src/lib/components/ui/chart/chart-tooltip.svelte create mode 100644 src/lib/components/ui/chart/chart-utils.ts create mode 100644 src/lib/components/ui/chart/index.ts create mode 100644 src/lib/components/ui/checkbox/checkbox.svelte create mode 100644 src/lib/components/ui/checkbox/index.ts create mode 100644 src/lib/components/ui/collapsible/collapsible-content.svelte create mode 100644 src/lib/components/ui/collapsible/collapsible-trigger.svelte create mode 100644 src/lib/components/ui/collapsible/collapsible.svelte create mode 100644 src/lib/components/ui/collapsible/index.ts create mode 100644 src/lib/components/ui/command/command-dialog.svelte create mode 100644 src/lib/components/ui/command/command-empty.svelte create mode 100644 src/lib/components/ui/command/command-group.svelte create mode 100644 src/lib/components/ui/command/command-input.svelte create mode 100644 src/lib/components/ui/command/command-item.svelte create mode 100644 src/lib/components/ui/command/command-link-item.svelte create mode 100644 src/lib/components/ui/command/command-list.svelte create mode 100644 src/lib/components/ui/command/command-loading.svelte create mode 100644 src/lib/components/ui/command/command-separator.svelte create mode 100644 src/lib/components/ui/command/command-shortcut.svelte create mode 100644 src/lib/components/ui/command/command.svelte create mode 100644 src/lib/components/ui/command/index.ts create mode 100644 src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-content.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-group-heading.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-group.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-item.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-label.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-portal.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-radio-group.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-radio-item.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-separator.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-shortcut.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-sub-content.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-sub.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu-trigger.svelte create mode 100644 src/lib/components/ui/context-menu/context-menu.svelte create mode 100644 src/lib/components/ui/context-menu/index.ts create mode 100644 src/lib/components/ui/data-table/data-table.svelte.ts create mode 100644 src/lib/components/ui/data-table/flex-render.svelte create mode 100644 src/lib/components/ui/data-table/index.ts create mode 100644 src/lib/components/ui/data-table/render-helpers.ts create mode 100644 src/lib/components/ui/dialog/dialog-close.svelte create mode 100644 src/lib/components/ui/dialog/dialog-content.svelte create mode 100644 src/lib/components/ui/dialog/dialog-description.svelte create mode 100644 src/lib/components/ui/dialog/dialog-footer.svelte create mode 100644 src/lib/components/ui/dialog/dialog-header.svelte create mode 100644 src/lib/components/ui/dialog/dialog-overlay.svelte create mode 100644 src/lib/components/ui/dialog/dialog-portal.svelte create mode 100644 src/lib/components/ui/dialog/dialog-title.svelte create mode 100644 src/lib/components/ui/dialog/dialog-trigger.svelte create mode 100644 src/lib/components/ui/dialog/dialog.svelte create mode 100644 src/lib/components/ui/dialog/index.ts create mode 100644 src/lib/components/ui/drawer/drawer-close.svelte create mode 100644 src/lib/components/ui/drawer/drawer-content.svelte create mode 100644 src/lib/components/ui/drawer/drawer-description.svelte create mode 100644 src/lib/components/ui/drawer/drawer-footer.svelte create mode 100644 src/lib/components/ui/drawer/drawer-header.svelte create mode 100644 src/lib/components/ui/drawer/drawer-nested.svelte create mode 100644 src/lib/components/ui/drawer/drawer-overlay.svelte create mode 100644 src/lib/components/ui/drawer/drawer-portal.svelte create mode 100644 src/lib/components/ui/drawer/drawer-title.svelte create mode 100644 src/lib/components/ui/drawer/drawer-trigger.svelte create mode 100644 src/lib/components/ui/drawer/drawer.svelte create mode 100644 src/lib/components/ui/drawer/index.ts create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte create mode 100644 src/lib/components/ui/dropdown-menu/dropdown-menu.svelte create mode 100644 src/lib/components/ui/dropdown-menu/index.ts create mode 100644 src/lib/components/ui/empty/empty-content.svelte create mode 100644 src/lib/components/ui/empty/empty-description.svelte create mode 100644 src/lib/components/ui/empty/empty-header.svelte create mode 100644 src/lib/components/ui/empty/empty-media.svelte create mode 100644 src/lib/components/ui/empty/empty-title.svelte create mode 100644 src/lib/components/ui/empty/empty.svelte create mode 100644 src/lib/components/ui/empty/index.ts create mode 100644 src/lib/components/ui/field/field-content.svelte create mode 100644 src/lib/components/ui/field/field-description.svelte create mode 100644 src/lib/components/ui/field/field-error.svelte create mode 100644 src/lib/components/ui/field/field-group.svelte create mode 100644 src/lib/components/ui/field/field-label.svelte create mode 100644 src/lib/components/ui/field/field-legend.svelte create mode 100644 src/lib/components/ui/field/field-separator.svelte create mode 100644 src/lib/components/ui/field/field-set.svelte create mode 100644 src/lib/components/ui/field/field-title.svelte create mode 100644 src/lib/components/ui/field/field.svelte create mode 100644 src/lib/components/ui/field/index.ts create mode 100644 src/lib/components/ui/form/form-button.svelte create mode 100644 src/lib/components/ui/form/form-description.svelte create mode 100644 src/lib/components/ui/form/form-element-field.svelte create mode 100644 src/lib/components/ui/form/form-field-errors.svelte create mode 100644 src/lib/components/ui/form/form-field.svelte create mode 100644 src/lib/components/ui/form/form-fieldset.svelte create mode 100644 src/lib/components/ui/form/form-label.svelte create mode 100644 src/lib/components/ui/form/form-legend.svelte create mode 100644 src/lib/components/ui/form/index.ts create mode 100644 src/lib/components/ui/hover-card/hover-card-content.svelte create mode 100644 src/lib/components/ui/hover-card/hover-card-portal.svelte create mode 100644 src/lib/components/ui/hover-card/hover-card-trigger.svelte create mode 100644 src/lib/components/ui/hover-card/hover-card.svelte create mode 100644 src/lib/components/ui/hover-card/index.ts create mode 100644 src/lib/components/ui/input-group/index.ts create mode 100644 src/lib/components/ui/input-group/input-group-addon.svelte create mode 100644 src/lib/components/ui/input-group/input-group-button.svelte create mode 100644 src/lib/components/ui/input-group/input-group-input.svelte create mode 100644 src/lib/components/ui/input-group/input-group-text.svelte create mode 100644 src/lib/components/ui/input-group/input-group-textarea.svelte create mode 100644 src/lib/components/ui/input-group/input-group.svelte create mode 100644 src/lib/components/ui/input-otp/index.ts create mode 100644 src/lib/components/ui/input-otp/input-otp-group.svelte create mode 100644 src/lib/components/ui/input-otp/input-otp-separator.svelte create mode 100644 src/lib/components/ui/input-otp/input-otp-slot.svelte create mode 100644 src/lib/components/ui/input-otp/input-otp.svelte create mode 100644 src/lib/components/ui/input/index.ts create mode 100644 src/lib/components/ui/input/input.svelte create mode 100644 src/lib/components/ui/item/index.ts create mode 100644 src/lib/components/ui/item/item-actions.svelte create mode 100644 src/lib/components/ui/item/item-content.svelte create mode 100644 src/lib/components/ui/item/item-description.svelte create mode 100644 src/lib/components/ui/item/item-footer.svelte create mode 100644 src/lib/components/ui/item/item-group.svelte create mode 100644 src/lib/components/ui/item/item-header.svelte create mode 100644 src/lib/components/ui/item/item-media.svelte create mode 100644 src/lib/components/ui/item/item-separator.svelte create mode 100644 src/lib/components/ui/item/item-title.svelte create mode 100644 src/lib/components/ui/item/item.svelte create mode 100644 src/lib/components/ui/kbd/index.ts create mode 100644 src/lib/components/ui/kbd/kbd-group.svelte create mode 100644 src/lib/components/ui/kbd/kbd.svelte create mode 100644 src/lib/components/ui/label/index.ts create mode 100644 src/lib/components/ui/label/label.svelte create mode 100644 src/lib/components/ui/menubar/index.ts create mode 100644 src/lib/components/ui/menubar/menubar-checkbox-item.svelte create mode 100644 src/lib/components/ui/menubar/menubar-content.svelte create mode 100644 src/lib/components/ui/menubar/menubar-group-heading.svelte create mode 100644 src/lib/components/ui/menubar/menubar-group.svelte create mode 100644 src/lib/components/ui/menubar/menubar-item.svelte create mode 100644 src/lib/components/ui/menubar/menubar-label.svelte create mode 100644 src/lib/components/ui/menubar/menubar-menu.svelte create mode 100644 src/lib/components/ui/menubar/menubar-portal.svelte create mode 100644 src/lib/components/ui/menubar/menubar-radio-group.svelte create mode 100644 src/lib/components/ui/menubar/menubar-radio-item.svelte create mode 100644 src/lib/components/ui/menubar/menubar-separator.svelte create mode 100644 src/lib/components/ui/menubar/menubar-shortcut.svelte create mode 100644 src/lib/components/ui/menubar/menubar-sub-content.svelte create mode 100644 src/lib/components/ui/menubar/menubar-sub-trigger.svelte create mode 100644 src/lib/components/ui/menubar/menubar-sub.svelte create mode 100644 src/lib/components/ui/menubar/menubar-trigger.svelte create mode 100644 src/lib/components/ui/menubar/menubar.svelte create mode 100644 src/lib/components/ui/native-select/index.ts create mode 100644 src/lib/components/ui/native-select/native-select-opt-group.svelte create mode 100644 src/lib/components/ui/native-select/native-select-option.svelte create mode 100644 src/lib/components/ui/native-select/native-select.svelte create mode 100644 src/lib/components/ui/navigation-menu/index.ts create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-content.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-indicator.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-item.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-link.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-list.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-trigger.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu-viewport.svelte create mode 100644 src/lib/components/ui/navigation-menu/navigation-menu.svelte create mode 100644 src/lib/components/ui/pagination/index.ts create mode 100644 src/lib/components/ui/pagination/pagination-content.svelte create mode 100644 src/lib/components/ui/pagination/pagination-ellipsis.svelte create mode 100644 src/lib/components/ui/pagination/pagination-item.svelte create mode 100644 src/lib/components/ui/pagination/pagination-link.svelte create mode 100644 src/lib/components/ui/pagination/pagination-next-button.svelte create mode 100644 src/lib/components/ui/pagination/pagination-next.svelte create mode 100644 src/lib/components/ui/pagination/pagination-prev-button.svelte create mode 100644 src/lib/components/ui/pagination/pagination-previous.svelte create mode 100644 src/lib/components/ui/pagination/pagination.svelte create mode 100644 src/lib/components/ui/popover/index.ts create mode 100644 src/lib/components/ui/popover/popover-close.svelte create mode 100644 src/lib/components/ui/popover/popover-content.svelte create mode 100644 src/lib/components/ui/popover/popover-description.svelte create mode 100644 src/lib/components/ui/popover/popover-header.svelte create mode 100644 src/lib/components/ui/popover/popover-portal.svelte create mode 100644 src/lib/components/ui/popover/popover-title.svelte create mode 100644 src/lib/components/ui/popover/popover-trigger.svelte create mode 100644 src/lib/components/ui/popover/popover.svelte create mode 100644 src/lib/components/ui/progress/index.ts create mode 100644 src/lib/components/ui/progress/progress.svelte create mode 100644 src/lib/components/ui/radio-group/index.ts create mode 100644 src/lib/components/ui/radio-group/radio-group-item.svelte create mode 100644 src/lib/components/ui/radio-group/radio-group.svelte create mode 100644 src/lib/components/ui/range-calendar/index.ts create mode 100644 src/lib/components/ui/range-calendar/range-calendar-caption.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-cell.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-day.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-grid.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-header.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-heading.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-month-select.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-month.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-months.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-nav.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-next-button.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar-year-select.svelte create mode 100644 src/lib/components/ui/range-calendar/range-calendar.svelte create mode 100644 src/lib/components/ui/resizable/index.ts create mode 100644 src/lib/components/ui/resizable/resizable-handle.svelte create mode 100644 src/lib/components/ui/resizable/resizable-pane-group.svelte create mode 100644 src/lib/components/ui/scroll-area/index.ts create mode 100644 src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte create mode 100644 src/lib/components/ui/scroll-area/scroll-area.svelte create mode 100644 src/lib/components/ui/select/index.ts create mode 100644 src/lib/components/ui/select/select-content.svelte create mode 100644 src/lib/components/ui/select/select-group-heading.svelte create mode 100644 src/lib/components/ui/select/select-group.svelte create mode 100644 src/lib/components/ui/select/select-item.svelte create mode 100644 src/lib/components/ui/select/select-label.svelte create mode 100644 src/lib/components/ui/select/select-portal.svelte create mode 100644 src/lib/components/ui/select/select-scroll-down-button.svelte create mode 100644 src/lib/components/ui/select/select-scroll-up-button.svelte create mode 100644 src/lib/components/ui/select/select-separator.svelte create mode 100644 src/lib/components/ui/select/select-trigger.svelte create mode 100644 src/lib/components/ui/select/select.svelte create mode 100644 src/lib/components/ui/separator/index.ts create mode 100644 src/lib/components/ui/separator/separator.svelte create mode 100644 src/lib/components/ui/sheet/index.ts create mode 100644 src/lib/components/ui/sheet/sheet-close.svelte create mode 100644 src/lib/components/ui/sheet/sheet-content.svelte create mode 100644 src/lib/components/ui/sheet/sheet-description.svelte create mode 100644 src/lib/components/ui/sheet/sheet-footer.svelte create mode 100644 src/lib/components/ui/sheet/sheet-header.svelte create mode 100644 src/lib/components/ui/sheet/sheet-overlay.svelte create mode 100644 src/lib/components/ui/sheet/sheet-portal.svelte create mode 100644 src/lib/components/ui/sheet/sheet-title.svelte create mode 100644 src/lib/components/ui/sheet/sheet-trigger.svelte create mode 100644 src/lib/components/ui/sheet/sheet.svelte create mode 100644 src/lib/components/ui/sidebar/constants.ts create mode 100644 src/lib/components/ui/sidebar/context.svelte.ts create mode 100644 src/lib/components/ui/sidebar/index.ts create mode 100644 src/lib/components/ui/sidebar/sidebar-content.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-footer.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-group-action.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-group-content.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-group-label.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-group.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-header.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-input.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-inset.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-action.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-badge.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-button.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-item.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu-sub.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-menu.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-provider.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-rail.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-separator.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar-trigger.svelte create mode 100644 src/lib/components/ui/sidebar/sidebar.svelte create mode 100644 src/lib/components/ui/skeleton/index.ts create mode 100644 src/lib/components/ui/skeleton/skeleton.svelte create mode 100644 src/lib/components/ui/slider/index.ts create mode 100644 src/lib/components/ui/slider/slider.svelte create mode 100644 src/lib/components/ui/sonner/index.ts create mode 100644 src/lib/components/ui/sonner/sonner.svelte create mode 100644 src/lib/components/ui/spinner/index.ts create mode 100644 src/lib/components/ui/spinner/spinner.svelte create mode 100644 src/lib/components/ui/switch/index.ts create mode 100644 src/lib/components/ui/switch/switch.svelte create mode 100644 src/lib/components/ui/table/index.ts create mode 100644 src/lib/components/ui/table/table-body.svelte create mode 100644 src/lib/components/ui/table/table-caption.svelte create mode 100644 src/lib/components/ui/table/table-cell.svelte create mode 100644 src/lib/components/ui/table/table-footer.svelte create mode 100644 src/lib/components/ui/table/table-head.svelte create mode 100644 src/lib/components/ui/table/table-header.svelte create mode 100644 src/lib/components/ui/table/table-row.svelte create mode 100644 src/lib/components/ui/table/table.svelte create mode 100644 src/lib/components/ui/tabs/index.ts create mode 100644 src/lib/components/ui/tabs/tabs-content.svelte create mode 100644 src/lib/components/ui/tabs/tabs-list.svelte create mode 100644 src/lib/components/ui/tabs/tabs-trigger.svelte create mode 100644 src/lib/components/ui/tabs/tabs.svelte create mode 100644 src/lib/components/ui/textarea/index.ts create mode 100644 src/lib/components/ui/textarea/textarea.svelte create mode 100644 src/lib/components/ui/toggle-group/index.ts create mode 100644 src/lib/components/ui/toggle-group/toggle-group-item.svelte create mode 100644 src/lib/components/ui/toggle-group/toggle-group.svelte create mode 100644 src/lib/components/ui/toggle/index.ts create mode 100644 src/lib/components/ui/toggle/toggle.svelte create mode 100644 src/lib/components/ui/tooltip/index.ts create mode 100644 src/lib/components/ui/tooltip/tooltip-content.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip-portal.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip-provider.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip-trigger.svelte create mode 100644 src/lib/components/ui/tooltip/tooltip.svelte create mode 100644 src/lib/const/schema.ts create mode 100644 src/lib/hooks/is-mobile.svelte.ts create mode 100644 src/lib/index.ts create mode 100644 src/lib/machines/schema.test.ts create mode 100644 src/lib/machines/schema.ts create mode 100644 src/lib/remotes/auth.remote.ts create mode 100644 src/lib/remotes/machines.remote.ts create mode 100644 src/lib/remotes/server.remote.ts create mode 100644 src/lib/remotes/users.remote.ts create mode 100644 src/lib/server/db/auth-schema.ts create mode 100644 src/lib/server/db/custom-types.ts create mode 100644 src/lib/server/db/index.ts create mode 100644 src/lib/server/db/schema.ts create mode 100644 src/lib/server/emails/auth/complete-registration.svelte create mode 100644 src/lib/server/emails/auth/layout.svelte create mode 100644 src/lib/server/emails/auth/otp.svelte create mode 100644 src/lib/server/emails/auth/reset-password.svelte create mode 100644 src/lib/server/emails/auth/verify-email.svelte create mode 100644 src/lib/server/emails/index.ts create mode 100644 src/lib/server/emails/schemas.ts create mode 100644 src/lib/server/emails/send.ts create mode 100644 src/lib/server/nadir-agent/client.ts create mode 100644 src/lib/server/nadir-agent/schema.d.ts create mode 100644 src/lib/utils.ts create mode 100644 src/routes/+layout.svelte create mode 100644 src/routes/+page.svelte create mode 100644 src/routes/admin/+layout.server.ts create mode 100644 src/routes/admin/+page.svelte create mode 100644 src/routes/admin/config/+page.svelte create mode 100644 src/routes/admin/users/+page.svelte create mode 100644 src/routes/api/emailer/send/+server.ts create mode 100644 src/routes/auth/+layout.svelte create mode 100644 src/routes/auth/2fa/+page.svelte create mode 100644 src/routes/auth/forgot-password/+page.svelte create mode 100644 src/routes/auth/reset-password/+page.svelte create mode 100644 src/routes/auth/setup-2fa/+page.svelte create mode 100644 src/routes/auth/sign-in/+page.svelte create mode 100644 src/routes/auth/sign-up/+page.svelte create mode 100644 src/routes/dashboard/+page.svelte create mode 100644 src/routes/dashboard/[machineId]/+page.svelte create mode 100644 src/routes/layout.css create mode 100644 src/routes/system/+page.svelte create mode 100644 src/routes/system/date-time/+page.svelte create mode 100644 src/routes/system/localization/+page.svelte create mode 100644 static/robots.txt create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..ecb40fd --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +# Drizzle +DATABASE_URL=file:local.db diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34bf0f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +node_modules + +# Output +.output +.vercel +.netlify +.wrangler +/.svelte-kit +/build + +# OS +.DS_Store +Thumbs.db + +# Env +.env +.env.* +!.env.example +!.env.test + +# Vite +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +# Paraglide +src/lib/paraglide +project.inlang/cache/ +# SQLite +*.db diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..0243576 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,10 @@ +# Package Managers +package-lock.json +pnpm-lock.yaml +yarn.lock +bun.lock +bun.lockb + +# Miscellaneous +/static/ +/drizzle/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..819fa57 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ], + "tailwindStylesheet": "./src/routes/layout.css" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..44167f8 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "svelte.svelte-vscode", + "esbenp.prettier-vscode", + "bradlc.vscode-tailwindcss", + "dbaeumer.vscode-eslint" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6c7b79a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "*.css": "tailwindcss" + }, + "eslint.format.enable": true +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f8e8fd --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# Nadir Web UI + +SvelteKit dashboard for [nadir-agent](https://tea.urania.dev/urania/nadir-agent) - +a central web console that talks to one or many Nadir backend nodes over their +typed REST API. + +The agent does the system-administration work (systemd services, users, +packages, networking, audit, terminal, ...). This UI is the operator's view of +it: sign in, register machines with their bearer token, see live host metrics +on the dashboard, and drive everyday tasks from the browser. + +--- + +## Stack + +- **SvelteKit** (Svelte 5, adapter-node) + **TailwindCSS 4** + **shadcn-svelte** +- **Bun** as the runtime / package manager / dev server +- **Drizzle ORM** on **SQLite** (libSQL driver) for the UI's own state (users, + machines, encrypted tokens) +- **Better Auth** with email/password, OAuth, optional 2FA, admin & username + plugins +- **Paraglide** for i18n (messages in `messages/`) +- **openapi-fetch** + typed client generated from the nadir-agent OpenAPI spec + (`src/lib/server/nadir-agent/schema.d.ts`) + +--- + +## Getting started + +Prerequisites: [Bun](https://bun.com) and a reachable nadir-agent instance with +a machine token (see the agent README's *Connecting a dashboard* section). + +```sh +bun install +cp .env.example .env # then edit (see below) +bun run db:push # creates db.sqlite from the Drizzle schema +bun run dev # starts on http://localhost:5173 +``` + +### Environment + +Set in `.env` (validated at startup via `src/lib/const/schema.ts`): + +| Var | Default | Purpose | +| --------------------------- | ----------------------- | ------------------------------------------------------ | +| `CRYPTO_SECRET` | (required) | Encrypts machine bearer tokens at rest in the local DB | +| `DATABASE_URL` | `file:db.sqlite` | libSQL connection string | +| `ORIGIN` | `http://localhost:5173` | Public origin (used by Better Auth) | +| `DISABLE_SIGNUP` | `false` | Lock down registration | +| `ENABLE_2FA` | `false` | Enable the TOTP 2FA flow | +| `ENABLE_EMAIL_AND_PASSWORD` | `true` | Toggle email/password auth | +| `SMTP_*` | - | Outbound mail for verification / reset / 2FA | + +OAuth providers (optional) live in `config/oauth.json` and are passed straight +to Better Auth's `genericOAuth` plugin. + +--- + +## Scripts + +```sh +bun run dev # vite dev server +bun run build # production build (adapter-node -> build/) +bun run preview # preview the production build +bun run check # svelte-check +bun run lint # prettier + eslint +bun run format # prettier --write +bun run db:push # apply schema to the DB +bun run db:generate # generate migration from schema changes +bun run db:migrate # run pending migrations +bun run db:studio # drizzle-kit studio +``` + +--- + +## Project layout + +``` +src/ + routes/ + auth/ sign-in, sign-up, forgot/reset password, 2fa setup + dashboard/ machine list and per-machine live dashboard + system/ date/time, localization + admin/ users, config + api/ internal endpoints (e.g. emailer) + lib/ + auth/ Better Auth server + client + components/ shadcn-svelte UI + dashboard panels (cpu, network, storage, ...) + machines/ valibot schemas + remotes/ SvelteKit remote functions (server.remote.ts, machines.remote.ts, ...) + server/ + db/ Drizzle schema + custom encrypted column type + emails/ nodemailer + better-svelte-email templates + nadir-agent/ generated OpenAPI types + typed client + paraglide/ generated i18n runtime +messages/ translation source (en, ...) +config/oauth.json optional OAuth providers passed to Better Auth +``` + +--- + +## Deploying + +`adapter-node` produces a plain Node/Bun server under `build/`: + +```sh +bun run build +PORT=3000 ORIGIN=https://nadir.example.com bun run build/index.js +``` + +Put it behind the same reverse proxy you use for nadir-agent, or co-host them. +The agent's CSRF rules apply when the UI calls it cross-origin - see the agent +README's *Connecting a dashboard* section. + +--- + +## License + +MIT. diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..d1cd2ce --- /dev/null +++ b/bun.lock @@ -0,0 +1,1376 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "clean", + "dependencies": { + "@better-auth/infra": "^0.2.14", + "@better-svelte-email/components": "^2.1.1", + "@better-svelte-email/server": "^2.1.1", + "better-auth": "^1.6.20", + "nodemailer": "^9.0.1", + "ogl": "^1.0.11", + "openapi-fetch": "^0.17.0", + "runed": "^0.37.1", + "uqr": "^0.1.3", + "valibot": "^1.4.1", + }, + "devDependencies": { + "@better-svelte-email/cli": "^2.1.1", + "@eslint/js": "^10.0.1", + "@fontsource-variable/geist": "^5.2.9", + "@inlang/paraglide-js": "^2.18.2", + "@internationalized/date": "^3.12.0", + "@libsql/client": "^0.17.3", + "@lucide/svelte": "^1.21.0", + "@sveltejs/adapter-node": "^5.5.4", + "@sveltejs/kit": "^2.63.0", + "@sveltejs/vite-plugin-svelte": "^7.1.2", + "@tailwindcss/vite": "^4.3.0", + "@tanstack/table-core": "^8.21.3", + "@types/bun": "^1.3.14", + "@types/node": "^24", + "@types/nodemailer": "^8.0.1", + "bits-ui": "^2.16.3", + "clsx": "^2.1.1", + "drizzle-kit": "^1.0.0-beta.22", + "drizzle-orm": "^1.0.0-beta.22", + "embla-carousel-svelte": "^8.6.0", + "eslint": "^10.4.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-perfectionist": "^5.9.1", + "eslint-plugin-svelte": "^3.19.0", + "formsnap": "^2.0.1", + "globals": "^17.6.0", + "layerchart": "2.0.0-next.48", + "mode-watcher": "^1.1.0", + "openapi-typescript": "^7.13.0", + "paneforge": "^1.0.2", + "prettier": "^3.8.3", + "prettier-plugin-svelte": "^4.1.0", + "prettier-plugin-tailwindcss": "^0.8.0", + "shadcn-svelte": "^1.3.0", + "svelte": "^5.56.1", + "svelte-check": "^4.6.0", + "svelte-sonner": "^1.1.0", + "sveltekit-superforms": "^2.30.0", + "tailwind-merge": "^3.5.0", + "tailwind-variants": "^3.2.2", + "tailwindcss": "^4.3.0", + "tw-animate-css": "^1.4.0", + "typescript": "^6.0.3", + "typescript-eslint": "^8.60.1", + "vaul-svelte": "^1.0.0-next.7", + "vite": "^8.0.16", + }, + }, + }, + "packages": { + "@ark/schema": ["@ark/schema@0.56.0", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA=="], + + "@ark/util": ["@ark/util@0.56.0", "", {}, "sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA=="], + + "@authenio/xml-encryption": ["@authenio/xml-encryption@2.0.2", "", { "dependencies": { "@xmldom/xmldom": "^0.8.6", "escape-html": "^1.0.3", "xpath": "0.0.32" } }, "sha512-cTlrKttbrRHEw3W+0/I609A2Matj5JQaRvfLtEIGZvlN0RaPi+3ANsMeqAyCAVlH/lUIW2tmtBlSMni74lcXeg=="], + + "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], + + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], + + "@better-auth/core": ["@better-auth/core@1.6.20", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.39.0", "@standard-schema/spec": "^1.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/utils": "0.4.2", "@better-fetch/fetch": "1.3.1", "@cloudflare/workers-types": ">=4", "@opentelemetry/api": "^1.9.0", "better-call": "1.3.6", "jose": "^6.1.0", "kysely": "^0.28.5 || ^0.29.0", "nanostores": "^1.0.1" }, "optionalPeers": ["@cloudflare/workers-types", "@opentelemetry/api"] }, "sha512-y73I1xNXuNYiHBFduWGRcJ2ro2rNuVDEYkgVMJtIaRXtbosdXHs9gfyQrHecgeHMHKx1SYSBT/CExak0vVMTng=="], + + "@better-auth/drizzle-adapter": ["@better-auth/drizzle-adapter@1.6.20", "", { "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2", "drizzle-orm": "^0.45.2" }, "optionalPeers": ["drizzle-orm"] }, "sha512-hJHfCdAiZrC7EmZAt3NAiGgcNo9Y5Qz3PLL+a9rODXaAJGCMvzUJniqef9wHuJBwU0SWW+2f4wXe8xQmaC/IKQ=="], + + "@better-auth/infra": ["@better-auth/infra@0.2.14", "", { "dependencies": { "@better-auth/utils": "^0.4.1", "@better-fetch/fetch": "^1.1.21", "better-call": "^1.3.2", "jose": "^6.1.0", "libphonenumber-js": "^1.13.3" }, "peerDependencies": { "@better-auth/core": ">=1.4.0", "@better-auth/sso": ">=1.4.0", "@react-native-async-storage/async-storage": ">=1.21.0", "better-auth": ">=1.4.0", "expo-constants": ">=16.0.0", "expo-crypto": ">=13.0.0", "expo-device": ">=6.0.0", "react-native": ">=0.74.0", "zod": ">=4.1.12" }, "optionalPeers": ["@react-native-async-storage/async-storage", "expo-constants", "expo-crypto", "expo-device", "react-native"] }, "sha512-CAX4b2ZaN7rKNEFuoQeHc3aBfWR6I6wPGOrmyb31eADEooNN9cp48Uz0bGF2Uq41bbxMe7KPJaI4iuliT/8tXg=="], + + "@better-auth/kysely-adapter": ["@better-auth/kysely-adapter@1.6.20", "", { "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2", "kysely": "^0.28.17 || ^0.29.0" }, "optionalPeers": ["kysely"] }, "sha512-Uvpmgbx5y8JqXroVanNzDdKzOl3HojoTz+/X6MR6zOUr25IzlYz660mjnu0rxKiIF55kD3CroqFsDzjNUw7ERw=="], + + "@better-auth/memory-adapter": ["@better-auth/memory-adapter@1.6.20", "", { "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2" } }, "sha512-J5Ni0LlFijbzXlwu2rFHaD8zEFocmajyzWkRnHsq8LhV/Dk4iWQwwnqzLrPoDQEj8roECAUF03hrIeMzqWRqJQ=="], + + "@better-auth/mongo-adapter": ["@better-auth/mongo-adapter@1.6.20", "", { "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2", "mongodb": "^6.0.0 || ^7.0.0" }, "optionalPeers": ["mongodb"] }, "sha512-ClDBJf6h4g85WJswxwQwxLaiyRU67Gmz/uaIf19tY1gqlLJDykSGjmqRNSBMG5rWABNzcNqbO4KG31rYUldbIw=="], + + "@better-auth/prisma-adapter": ["@better-auth/prisma-adapter@1.6.20", "", { "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@prisma/client", "prisma"] }, "sha512-WhYdhSGuVSfu1peCSf2snmmVzfWjRaEvbSrsNCusiwGE9l94HlES4mjSPM48fed24hL7yg4j1dYK/yjEt87FpQ=="], + + "@better-auth/sso": ["@better-auth/sso@1.6.20", "", { "dependencies": { "fast-xml-parser": "^5.8.0", "jose": "^6.1.3", "samlify": "^2.13.1", "tldts": "^6.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2", "@better-fetch/fetch": "1.3.1", "better-auth": "^1.6.20", "better-call": "1.3.6" } }, "sha512-cT3dthGkfDAz/k9jTtBOfsBtxsEgbO2hs5nSQlb0FdO3L/8MLi19iaIoQd1dmEun93MNqenZmYEZrPDKWWiISQ=="], + + "@better-auth/telemetry": ["@better-auth/telemetry@1.6.20", "", { "peerDependencies": { "@better-auth/core": "^1.6.20", "@better-auth/utils": "0.4.2", "@better-fetch/fetch": "1.3.1" } }, "sha512-3BhbY3naQDERvdJvJ7fGszVY6rpsVfc6c9uyBVZlC1coVEF/rkM0rIcjtMVI1GUH7vWy1wjR6qF5vQnMun3XNQ=="], + + "@better-auth/utils": ["@better-auth/utils@0.4.2", "", { "dependencies": { "@noble/hashes": "^2.0.1" } }, "sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A=="], + + "@better-fetch/fetch": ["@better-fetch/fetch@1.3.1", "", {}, "sha512-ABkD1WhyfPZprKRQI3bhATjeiFuNWC9PXhfGWqL+sg/gKrM977oFrYkdb4msM3hgUGonr7KlOsOFT5TU2rht9g=="], + + "@better-svelte-email/cli": ["@better-svelte-email/cli@2.1.1", "", { "dependencies": { "@better-svelte-email/preview-server": "2.1.1", "@better-svelte-email/server": "2.1.1", "@sveltejs/kit": "^2.61.0", "@sveltejs/vite-plugin-svelte": "^7.1.2", "chokidar": "^5.0.0", "commander": "^14.0.3", "prettier": "^3.8.3", "resend": "^6.12.3", "svelte": "^5.55.9", "vite": "^8.0.14" }, "bin": { "bse": "dist/index.cjs" } }, "sha512-CCXnYQU30EjU8WTH5yUcT3G7alaClRbNFfFjJdDw0Ds7hpF7FjLA3lTD7wCqYjYT/6YCEUkdoEpPS9VQ1QVJAQ=="], + + "@better-svelte-email/components": ["@better-svelte-email/components@2.1.1", "", { "peerDependencies": { "@sveltejs/kit": ">=2", "svelte": ">=5.14.3" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-1YDr3h/9yBQKUei7oZwT2I0ZTHFcA4SOdRh6MCng1gHHJsOHCGppwKpE3cteabkYo51Gr4JG3iInt3dpCq9V7g=="], + + "@better-svelte-email/preview-server": ["@better-svelte-email/preview-server@2.1.1", "", { "dependencies": { "@lucide/svelte": "^1.16.0", "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.61.0", "@tailwindcss/vite": "^4.3.0", "clsx": "^2.1.1", "runed": "^0.37.1", "shiki": "^4.1.0", "svelte-themes": "^2.0.10", "tailwind-merge": "^3.6.0", "tailwind-variants": "^3.2.2", "tailwindcss": "^4.3.0", "tw-animate-css": "^1.4.0", "vite": "^8.0.14" } }, "sha512-qZxz9zlv3LPo5tArKs9hjT8K8e2aJrlMqaJq9ekjnKnEaOpdzJpmv3EBkPS7vMZFLrbmYW09a03AFzx/cMQmHQ=="], + + "@better-svelte-email/server": ["@better-svelte-email/server@2.1.1", "", { "dependencies": { "html-to-text": "^10.0.0", "parse5": "^8.0.1", "postcss": "^8.5.15", "postcss-value-parser": "^4.2.0", "tailwindcss": "^4.3.0" }, "peerDependencies": { "svelte": ">=5.14.3" } }, "sha512-j7t7ROnyI65RHd+59Hq9i5lNalj/ueKZC07DF4DQX4T90mh1kdvquenQD0nyC10DSMGBKjEXQmdW3eWcV5+xSA=="], + + "@dagrejs/dagre": ["@dagrejs/dagre@2.0.4", "", { "dependencies": { "@dagrejs/graphlib": "3.0.4" } }, "sha512-J6vCWTNpicHF4zFlZG1cS5DkGzMr9941gddYkakjrg3ZNev4bbqEgLHFTWiFrcJm7UCRu7olO3K6IRDd9gSGhA=="], + + "@dagrejs/graphlib": ["@dagrejs/graphlib@3.0.4", "", {}, "sha512-HxZ7fCvAwTLCWCO0WjDkzAFQze8LdC6iOpKbetDKHIuDfIgMlIzYzqZ4nxwLlclQX+3ZVeZ1K2OuaOE2WWcyOg=="], + + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="], + + "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.6.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA=="], + + "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], + + "@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="], + + "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.2", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A=="], + + "@exodus/schemasafe": ["@exodus/schemasafe@1.3.0", "", {}, "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw=="], + + "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], + + "@fontsource-variable/geist": ["@fontsource-variable/geist@5.2.9", "", {}, "sha512-TP+QSBG3wxKGPE33CbMy/L0Nu3qvJ6Fy81Yc4LnQ95xH+i+cfEp8fyU8/kfV14YwszxIFPhnoMTbjL71waVpyQ=="], + + "@hapi/hoek": ["@hapi/hoek@9.3.0", "", {}, "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="], + + "@hapi/topo": ["@hapi/topo@5.1.0", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg=="], + + "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="], + + "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="], + + "@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@inlang/paraglide-js": ["@inlang/paraglide-js@2.20.0", "", { "dependencies": { "@inlang/recommend-sherlock": "^0.2.1", "@inlang/sdk": "^2.10.0", "commander": "11.1.0", "consola": "3.4.0", "json5": "2.2.3", "unplugin": "^2.1.2", "urlpattern-polyfill": "^10.0.0" }, "peerDependencies": { "typescript": ">=5.6" }, "optionalPeers": ["typescript"], "bin": { "paraglide-js": "bin/run.js" } }, "sha512-vI8PdPVZSnpYnpagjvm+nWSa3nMDRJKVM/2eLAtUHFrNcZZadxVdmP79r4W95+dkMLDFGEyzSSY9sFxvjdkkyQ=="], + + "@inlang/recommend-sherlock": ["@inlang/recommend-sherlock@0.2.1", "", { "dependencies": { "comment-json": "^4.2.3" } }, "sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg=="], + + "@inlang/sdk": ["@inlang/sdk@2.10.2", "", { "dependencies": { "@lix-js/sdk": "0.4.10", "@sinclair/typebox": "^0.31.17", "kysely": "^0.28.12", "sqlite-wasm-kysely": "0.3.0", "uuid": "^14.0.0" } }, "sha512-O1ki72SNK6LPagaGrvlioBb1mWKvump7cO7P85hfGZjdFTmDdn3icI0A6MvaBsB3P9KQHAjzyubnN1OslGufTw=="], + + "@internationalized/date": ["@internationalized/date@3.12.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@js-temporal/polyfill": ["@js-temporal/polyfill@0.5.1", "", { "dependencies": { "jsbi": "^4.3.0" } }, "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ=="], + + "@layerstack/svelte-actions": ["@layerstack/svelte-actions@1.0.1-next.18", "", { "dependencies": { "@floating-ui/dom": "^1.7.0", "@layerstack/utils": "2.0.0-next.18", "d3-scale": "^4.0.2" } }, "sha512-gxPzCnJ1c9LTfWtRqLUzefCx+k59ZpxDUQ2XB+LokveZQPe7IDSOwHaBOEMlaGoGrtwc3Ft8dSZq+2WT2o9u/g=="], + + "@layerstack/svelte-state": ["@layerstack/svelte-state@0.1.0-next.23", "", { "dependencies": { "@layerstack/utils": "2.0.0-next.18" } }, "sha512-7O4umv+gXwFfs3/vjzFWYHNXGwYnnjBapWJ5Y+9u99F4eVk6rh4ocNwqkqQNkpMZ5tUJBlRTWjPE1So6+hEzIg=="], + + "@layerstack/tailwind": ["@layerstack/tailwind@2.0.0-next.21", "", { "dependencies": { "@layerstack/utils": "^2.0.0-next.18", "clsx": "^2.1.1", "d3-array": "^3.2.4", "tailwind-merge": "^3.2.0" } }, "sha512-Qgp2EpmEHmjtura8MQzWicR6ztBRSsRvddakFtx9ShrLMz6jWzd6bCMVVRu44Q3ZOrtXmSu4QxjCZWu1ytvuPg=="], + + "@layerstack/utils": ["@layerstack/utils@2.0.0-next.18", "", { "dependencies": { "d3-array": "^3.2.4", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0" } }, "sha512-EYILHpfBRYMMEahajInu9C2AXQom5IcAEdtCeucD3QIl/fdDgRbtzn6/8QW9ewumfyNZetdUvitOksmI1+gZYQ=="], + + "@libsql/client": ["@libsql/client@0.17.4", "", { "dependencies": { "@libsql/core": "^0.17.4", "@libsql/hrana-client": "^0.10.0", "js-base64": "^3.7.5", "libsql": "^0.5.28", "promise-limit": "^2.7.0" } }, "sha512-lYayFWasDV78A+TjlEhr6ubb3odBV6OHjb+wdp8VQcyWWAEIjuwbCHaraEUS4m4yWoo0BvZo96It4VdzZRmRWw=="], + + "@libsql/core": ["@libsql/core@0.17.4", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-LqF9gIvnJ38nmAH1y/ChizHqDO/MO1wLgA96XrraulEEbqXxLjleSH92YWTolbuJKgPUmGu4aJk9W3UnAcxLOQ=="], + + "@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.29", "", { "os": "darwin", "cpu": "arm64" }, "sha512-K+2RIB1OGFPYQbfay48GakLhqf3ArcbHqPFu7EZiaUcRgFcdw8RoltsMyvbj5ix2fY0HV3Q3Ioa/ByvQdaSM0A=="], + + "@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.29", "", { "os": "darwin", "cpu": "x64" }, "sha512-OtT+KFHsKFy1R5FVadr8FJ2Bb1mghtXTyJkxv0trocq7NuHntSki1eUbxpO5ezJesDvBlqFjnWaYYY516QNLhQ=="], + + "@libsql/hrana-client": ["@libsql/hrana-client@0.10.0", "", { "dependencies": { "@libsql/isomorphic-ws": "^0.1.5", "js-base64": "^3.7.5" } }, "sha512-OoA4EMqRAC7kn7V2P6EQqRcpZf2W+AjsNIyCizBg339Tq/aMC7sRnzs3SklderhmQWAqEzvv8A2vhxVmWpkVvw=="], + + "@libsql/isomorphic-ws": ["@libsql/isomorphic-ws@0.1.5", "", { "dependencies": { "@types/ws": "^8.5.4", "ws": "^8.13.0" } }, "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg=="], + + "@libsql/linux-arm-gnueabihf": ["@libsql/linux-arm-gnueabihf@0.5.29", "", { "os": "linux", "cpu": "arm" }, "sha512-CD4n4zj7SJTHso4nf5cuMoWoMSS7asn5hHygsDuhRl8jjjCTT3yE+xdUvI4J7zsyb53VO5ISh4cwwOtf6k2UhQ=="], + + "@libsql/linux-arm-musleabihf": ["@libsql/linux-arm-musleabihf@0.5.29", "", { "os": "linux", "cpu": "arm" }, "sha512-2Z9qBVpEJV7OeflzIR3+l5yAd4uTOLxklScYTwpZnkm2vDSGlC1PRlueLaufc4EFITkLKXK2MWBpexuNJfMVcg=="], + + "@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.29", "", { "os": "linux", "cpu": "arm64" }, "sha512-gURBqaiXIGGwFNEaUj8Ldk7Hps4STtG+31aEidCk5evMMdtsdfL3HPCpvys+ZF/tkOs2MWlRWoSq7SOuCE9k3w=="], + + "@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.29", "", { "os": "linux", "cpu": "arm64" }, "sha512-fwgYZ0H8mUkyVqXZHF3mT/92iIh1N94Owi/f66cPVNsk9BdGKq5gVpoKO+7UxaNzuEH1roJp2QEwsCZMvBLpqg=="], + + "@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.29", "", { "os": "linux", "cpu": "x64" }, "sha512-y14V0vY0nmMC6G0pHeJcEarcnGU2H6cm21ZceRkacWHvQAEhAG0latQkCtoS2njFOXiYIg+JYPfAoWKbi82rkg=="], + + "@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.29", "", { "os": "linux", "cpu": "x64" }, "sha512-gquqwA/39tH4pFl+J9n3SOMSymjX+6kZ3kWgY3b94nXFTwac9bnFNMffIomgvlFaC4ArVqMnOZD3nuJ3H3VO1w=="], + + "@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.29", "", { "os": "win32", "cpu": "x64" }, "sha512-4/0CvEdhi6+KjMxMaVbFM2n2Z44escBRoEYpR+gZg64DdetzGnYm8mcNLcoySaDJZNaBd6wz5DNdgRmcI4hXcg=="], + + "@lix-js/sdk": ["@lix-js/sdk@0.4.10", "", { "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.28.12", "sqlite-wasm-kysely": "0.3.0", "uuid": "^14.0.0" } }, "sha512-0dMInAJK/67guTG5rRZaCEhvzC5cCXENOjaePA5AqMXrCE97kaY7SRor9e2vnoGsFIiGqXKlT0MCIoZj36G0gg=="], + + "@lix-js/server-protocol-schema": ["@lix-js/server-protocol-schema@0.1.1", "", {}, "sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ=="], + + "@lucide/svelte": ["@lucide/svelte@1.21.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-MEv//A7Jv3kHukZowv/DWp1MAtUzJKYwtJsmnQ7X98lCgtac3z3NbaToDl3Q6jO3gS9sougFpcD+t+YuxOkRMw=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.5", "", { "dependencies": { "@tybys/wasm-util": "^0.10.2" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q=="], + + "@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="], + + "@noble/ciphers": ["@noble/ciphers@2.2.0", "", {}, "sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA=="], + + "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], + + "@nodable/entities": ["@nodable/entities@2.2.0", "", {}, "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg=="], + + "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.41.1", "", {}, "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA=="], + + "@oxc-project/types": ["@oxc-project/types@0.133.0", "", {}, "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA=="], + + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], + + "@poppinss/macroable": ["@poppinss/macroable@1.1.2", "", {}, "sha512-FAVBRzzWhYP5mA3lCwLH1A0fKBqq5anyjGet90Z81aRK5c/+LTGUE1zJhZrErjaenBSOOI9BVUs3WVmotneFQA=="], + + "@redocly/ajv": ["@redocly/ajv@8.11.2", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js-replace": "^1.0.1" } }, "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg=="], + + "@redocly/config": ["@redocly/config@0.22.0", "", {}, "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ=="], + + "@redocly/openapi-core": ["@redocly/openapi-core@1.34.15", "", { "dependencies": { "@redocly/ajv": "8.11.2", "@redocly/config": "0.22.0", "colorette": "1.4.0", "https-proxy-agent": "7.0.6", "js-levenshtein": "1.1.6", "js-yaml": "4.1.1", "minimatch": "5.1.9", "pluralize": "8.0.0", "yaml-ast-parser": "0.0.43" } }, "sha512-HAwCnNyKcs5XGQqms+9t7OdAPM/5TDstmhF+0i7tdCFato2QKuYIlyWETwkXd8c5zbltr1oB+6y9NTeQLr2d6Q=="], + + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.3", "", { "os": "android", "cpu": "arm64" }, "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.3", "", { "os": "linux", "cpu": "arm" }, "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q=="], + + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg=="], + + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.3", "", { "os": "linux", "cpu": "x64" }, "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg=="], + + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.3", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], + + "@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@29.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg=="], + + "@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="], + + "@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.62.2", "", { "os": "android", "cpu": "arm" }, "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.62.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.62.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.62.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.62.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.62.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.62.2", "", { "os": "linux", "cpu": "arm" }, "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.62.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.62.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.62.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.62.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.62.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.62.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.62.2", "", { "os": "none", "cpu": "arm64" }, "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.62.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.62.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.62.2", "", { "os": "win32", "cpu": "x64" }, "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.62.2", "", { "os": "win32", "cpu": "x64" }, "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA=="], + + "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.12.0", "", { "dependencies": { "domelementtype": "~2.3.0", "domhandler": "~5.0.3" }, "peerDependencies": { "selderee": "~0.12.0" } }, "sha512-oELmoyA6ML9jDRMV3kgcMQFKxUfBU0yFVn6yTctVaLT5ygXnxH52I3TZEgV9EhXJC68/uFvE5Daj1/25c0Xa/A=="], + + "@shikijs/core": ["@shikijs/core@4.2.0", "", { "dependencies": { "@shikijs/primitive": "4.2.0", "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-Hc87Ab1Ld/vEbZRCbwx344I5v+4RU8CVToUTRkqXL1+TjbuOp9U5Xa0M23V4GEWHxVn+yO5otb+HkQVm3ptWQQ=="], + + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.2.0", "", { "dependencies": { "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" } }, "sha512-fjETeq1k5ffyXqRgS6+3hpvqseLalp1kjNfRbXpUgWR8FpZ1CmQfiNHovc5lncYjt/Vg5JK/WJEmLahjwMa0og=="], + + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@4.2.0", "", { "dependencies": { "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-hTorK1dffPkpbMUk6Z+828PgRo7d07HbnizoP0hNPFjhxMHctj0Px/qoHeGMYafc6ju+u9iMldN4JbVzNQM++g=="], + + "@shikijs/langs": ["@shikijs/langs@4.2.0", "", { "dependencies": { "@shikijs/types": "4.2.0" } }, "sha512-bwrVRlJ0wUhZxAbVdvBbv2TTC9yLsh4C/IO5Ofz0T8MQntgDvyVnkbjw9vi50r1kx7RCIJdnJnjZAwmAsXFLZQ=="], + + "@shikijs/primitive": ["@shikijs/primitive@4.2.0", "", { "dependencies": { "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-NOq+DtUkVBJtZMVXL5A0vI0Xk8nvDYaXetFHSJFlOqjDZIVhIPRYFdGkSoElDqNuegikcc3A76SNUa8dTqtAYA=="], + + "@shikijs/themes": ["@shikijs/themes@4.2.0", "", { "dependencies": { "@shikijs/types": "4.2.0" } }, "sha512-RX8IHYeLv8Cu2W6ruc3RxUqWn0IYCqSrMBzi/uRGAmfyDNOnNO5BF/Px7o97n4XTpmFTo5GbRaazuOWj+2ak2w=="], + + "@shikijs/types": ["@shikijs/types@4.2.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-VT/MKtlpOhEPZloSH3Pb9WCZEBDoQVMa9jedp5UAwmJOar1DVc9DRODAxmYPW9M93IK4ryuqRejFfmlvlVDemw=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + + "@sideway/address": ["@sideway/address@4.1.5", "", { "dependencies": { "@hapi/hoek": "^9.0.0" } }, "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q=="], + + "@sideway/formula": ["@sideway/formula@3.0.1", "", {}, "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="], + + "@sideway/pinpoint": ["@sideway/pinpoint@2.0.0", "", {}, "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="], + + "@sinclair/typebox": ["@sinclair/typebox@0.31.28", "", {}, "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ=="], + + "@sqlite.org/sqlite-wasm": ["@sqlite.org/sqlite-wasm@3.48.0-build4", "", { "bin": { "sqlite-wasm": "bin/index.js" } }, "sha512-hI6twvUkzOmyGZhQMza1gpfqErZxXRw6JEsiVjUbo7tFanVD+8Oil0Ih3l2nGzHdxPI41zFmfUQG7GHqhciKZQ=="], + + "@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.10", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA=="], + + "@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.5.4", "", { "dependencies": { "@rollup/plugin-commonjs": "^29.0.0", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.59.0" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-45X92CXW+2J8ZUzPv3eLlKWEzINKiiGeFWTjyER4ZN4sGgNoaoeSkCY/QYNxHpPXy71QPsctwccBo9jJs0ySPQ=="], + + "@sveltejs/kit": ["@sveltejs/kit@2.66.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.9", "@types/cookie": "^0.6.0", "acorn": "^8.16.0", "cookie": "^0.6.0", "devalue": "^5.8.1", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3 || ^6.0.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-7nN4Ur4+nofZ36DVo83JbRe02m61Vc+I441mML/DYa1pUTZ/x26+lbrdqPen8gjmsUc6flMtHEqAtn0UfmfvAw=="], + + "@sveltejs/load-config": ["@sveltejs/load-config@0.1.1", "", {}, "sha512-BXXm+VOH/9X4N7Dd1iZ2MqA1h7M+9i2noI8QYuLDY8QcN2WHYn7D/VK/+IJNfcAmRw7ACNJ538UT9GXIhnBTiA=="], + + "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@7.1.2", "", { "dependencies": { "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.2" }, "peerDependencies": { "svelte": "^5.46.4", "vite": "^8.0.0-beta.7 || ^8.0.0" } }, "sha512-DrUBA2UXRfDmUX/ZTiEopd3X40yavsJF1FX2RygcuIScHL7o5YX1fMvoYnDhjeJQC4weCOklirpNWlcb2NiSeA=="], + + "@swc/helpers": ["@swc/helpers@0.5.23", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.3.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "5.21.6", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.1" } }, "sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.1", "@tailwindcss/oxide-darwin-arm64": "4.3.1", "@tailwindcss/oxide-darwin-x64": "4.3.1", "@tailwindcss/oxide-freebsd-x64": "4.3.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.1", "@tailwindcss/oxide-linux-arm64-musl": "4.3.1", "@tailwindcss/oxide-linux-x64-gnu": "4.3.1", "@tailwindcss/oxide-linux-x64-musl": "4.3.1", "@tailwindcss/oxide-wasm32-wasi": "4.3.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.1", "@tailwindcss/oxide-win32-x64-msvc": "4.3.1" } }, "sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.1", "", { "os": "android", "cpu": "arm64" }, "sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1", "", { "os": "linux", "cpu": "arm" }, "sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ=="], + + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.1", "", { "dependencies": { "@emnapi/core": "^1.10.0", "@emnapi/runtime": "^1.10.0", "@emnapi/wasi-threads": "^1.2.1", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA=="], + + "@tailwindcss/vite": ["@tailwindcss/vite@4.3.1", "", { "dependencies": { "@tailwindcss/node": "4.3.1", "@tailwindcss/oxide": "4.3.1", "tailwindcss": "4.3.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-hItDHuIIlEV61R+faXu66s1K36aTurO/Qw0e45Vskz57gXl9pWOT6eg3zmcEui6CZXddbN7zd41bwmvag4JGwQ=="], + + "@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], + + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], + + "@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="], + + "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="], + + "@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="], + + "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], + + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + + "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], + + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/node": ["@types/node@24.13.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA=="], + + "@types/nodemailer": ["@types/nodemailer@8.0.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-PxpaInm8V1JQDd4j0ds5HfvWQk8JupS1C0Picb96QJsrrRDjBH+DlK7L4ZdNSqNULhiZRQHc40nLVShaGxXAMw=="], + + "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], + + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@types/validator": ["@types/validator@13.15.10", "", {}, "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA=="], + + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + + "@typeschema/class-validator": ["@typeschema/class-validator@0.3.0", "", { "dependencies": { "@typeschema/core": "0.14.0" }, "peerDependencies": { "class-validator": "^0.14.1" }, "optionalPeers": ["class-validator"] }, "sha512-OJSFeZDIQ8EK1HTljKLT5CItM2wsbgczLN8tMEfz3I1Lmhc5TBfkZ0eikFzUC16tI3d1Nag7um6TfCgp2I2Bww=="], + + "@typeschema/core": ["@typeschema/core@0.14.0", "", { "peerDependencies": { "@types/json-schema": "^7.0.15" }, "optionalPeers": ["@types/json-schema"] }, "sha512-Ia6PtZHcL3KqsAWXjMi5xIyZ7XMH4aSnOQes8mfMLx+wGFGtGRNlwe6Y7cYvX+WfNK67OL0/HSe9t8QDygV0/w=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.61.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/type-utils": "8.61.1", "@typescript-eslint/utils": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.61.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.61.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/types": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.61.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.61.1", "@typescript-eslint/types": "^8.61.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.61.1", "", { "dependencies": { "@typescript-eslint/types": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1" } }, "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.61.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.61.1", "", { "dependencies": { "@typescript-eslint/types": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/utils": "8.61.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.61.1", "", {}, "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.1", "@typescript-eslint/tsconfig-utils": "8.61.1", "@typescript-eslint/types": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.61.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/types": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.1", "", { "dependencies": { "@typescript-eslint/types": "8.61.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w=="], + + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.1", "", {}, "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ=="], + + "@valibot/to-json-schema": ["@valibot/to-json-schema@1.7.1", "", { "peerDependencies": { "valibot": "^1.4.0" } }, "sha512-3qkmU6KXWh8GIThEAW3kuRHPQBMjWkKy+Ppz3WkUucx53DTpOa6siMn4xDGSOhlVyMrDaJTCTMLYPZVAIk1P0A=="], + + "@vinejs/compiler": ["@vinejs/compiler@3.0.0", "", {}, "sha512-v9Lsv59nR56+bmy2p0+czjZxsLHwaibJ+SV5iK9JJfehlJMa501jUJQqqz4X/OqKXrxtE3uTQmSqjUqzF3B2mw=="], + + "@vinejs/vine": ["@vinejs/vine@3.0.1", "", { "dependencies": { "@poppinss/macroable": "^1.0.4", "@types/validator": "^13.12.2", "@vinejs/compiler": "^3.0.0", "camelcase": "^8.0.0", "dayjs": "^1.11.13", "dlv": "^1.1.3", "normalize-url": "^8.0.1", "validator": "^13.12.0" } }, "sha512-ZtvYkYpZOYdvbws3uaOAvTFuvFXoQGAtmzeiXu+XSMGxi5GVsODpoI9Xu9TplEMuD/5fmAtBbKb9cQHkWkLXDQ=="], + + "@xmldom/is-dom-node": ["@xmldom/is-dom-node@1.0.1", "", {}, "sha512-CJDxIgE5I0FH+ttq/Fxy6nRpxP70+e2O048EPe85J2use3XKdatVM7dDVvFNjQudd9B49NPoZ+8PG49zj4Er8Q=="], + + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.13", "", {}, "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw=="], + + "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + + "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], + + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + + "anynum": ["anynum@1.0.1", "", {}, "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "aria-query": ["aria-query@5.3.1", "", {}, "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g=="], + + "arkregex": ["arkregex@0.0.6", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-9mvuMKQuibfWhBrsNYhsKhNb6k9oEHoAJ/FvDiqe8h+E9Siwe0/cro1WVOGgpajXQ9ZHd24yCOf2k35Q/QqUQw=="], + + "arktype": ["arktype@2.2.1", "", { "dependencies": { "@ark/schema": "0.56.0", "@ark/util": "0.56.0", "arkregex": "0.0.6" } }, "sha512-CWPJxNoSxrS+NYGB3ufwc/blFonESEW5vBQyYPVS0rf4STu8VWoAWfKJSl5vVVm56h4yxpwbODeYwy6XFKvojA=="], + + "array-timsort": ["array-timsort@1.0.3", "", {}, "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ=="], + + "asn1": ["asn1@0.2.6", "", { "dependencies": { "safer-buffer": "~2.1.0" } }, "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ=="], + + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + + "better-auth": ["better-auth@1.6.20", "", { "dependencies": { "@better-auth/core": "1.6.20", "@better-auth/drizzle-adapter": "1.6.20", "@better-auth/kysely-adapter": "1.6.20", "@better-auth/memory-adapter": "1.6.20", "@better-auth/mongo-adapter": "1.6.20", "@better-auth/prisma-adapter": "1.6.20", "@better-auth/telemetry": "1.6.20", "@better-auth/utils": "0.4.2", "@better-fetch/fetch": "1.3.1", "@noble/ciphers": "^2.1.1", "@noble/hashes": "^2.0.1", "better-call": "1.3.6", "defu": "^6.1.4", "jose": "^6.1.3", "kysely": "^0.28.17 || ^0.29.0", "nanostores": "^1.1.1", "zod": "^4.3.6" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": "^0.45.2", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-fSpGHGRKiGRiYVd3QTQtuVZ8oxpiSe/7ip0Rpvt/Sy8zQbEbVKUPMOhE0gLXg+FjqTUsIo7582hxUYxtEcqUpA=="], + + "better-call": ["better-call@1.3.6", "", { "dependencies": { "@better-auth/utils": "^0.4.0", "@better-fetch/fetch": "^1.1.21", "rou3": "^0.7.12", "set-cookie-parser": "^3.0.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-no1jI+h6Bkxs1NVBo4rONbVIzsPjZ8IUu7IHaJBiFwVX1XEQGN8KpHots5fSWmXe9nNyLuLIcgx6WEUcE6EDaA=="], + + "bits-ui": ["bits-ui@2.18.1", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-KkemzKFH4T3gt3H+P86JcnAWExjByv/6vlwjm/BoCwTPHu03yiCdxbghdJLvFReQTe0acCAiRcKfmixxD6XvlA=="], + + "brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], + + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + + "camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + + "class-validator": ["class-validator@0.14.4", "", { "dependencies": { "@types/validator": "^13.15.3", "libphonenumber-js": "^1.11.1", "validator": "^13.15.22" } }, "sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], + + "comment-json": ["comment-json@4.6.2", "", { "dependencies": { "array-timsort": "^1.0.3", "esprima": "^4.0.1" } }, "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w=="], + + "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], + + "consola": ["consola@3.4.0", "", {}, "sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA=="], + + "cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], + + "d3-chord": ["d3-chord@3.0.1", "", { "dependencies": { "d3-path": "1 - 3" } }, "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="], + + "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], + + "d3-contour": ["d3-contour@4.0.2", "", { "dependencies": { "d3-array": "^3.2.0" } }, "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="], + + "d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="], + + "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="], + + "d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="], + + "d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="], + + "d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="], + + "d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="], + + "d3-geo-voronoi": ["d3-geo-voronoi@2.1.0", "", { "dependencies": { "d3-array": "3", "d3-delaunay": "6", "d3-geo": "3", "d3-tricontour": "1" } }, "sha512-kqE4yYuOjPbKdBXG0xztCacPwkVSK2REF1opSNrnqqtXJmNcM++UbwQ8SxvwP6IQTj9RvIjjK4qeiVsEfj0Z2Q=="], + + "d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="], + + "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], + + "d3-interpolate-path": ["d3-interpolate-path@2.3.0", "", {}, "sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ=="], + + "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="], + + "d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="], + + "d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="], + + "d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="], + + "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], + + "d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="], + + "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="], + + "d3-tile": ["d3-tile@1.0.0", "", {}, "sha512-79fnTKpPMPDS5xQ0xuS9ir0165NEwwkFpe/DSOmc2Gl9ldYzKKRDWogmTTE8wAJ8NA7PMapNfEcyKhI9Lxdu5Q=="], + + "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], + + "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], + + "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], + + "d3-tricontour": ["d3-tricontour@1.1.0", "", { "dependencies": { "d3-delaunay": "6", "d3-scale": "4" } }, "sha512-G7gHKj89n2owmkGb6WX6ixcnQ0Kf/0wpa9VIh9DGdbHu8wdrlaHU4ir3/bFNERl8N8nn4G7e7qbtBG8N9caihQ=="], + + "dayjs": ["dayjs@1.11.21", "", {}, "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "dedent": ["dedent@1.5.1", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + + "deepmerge-ts": ["deepmerge-ts@7.1.5", "", {}, "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw=="], + + "defu": ["defu@6.1.7", "", {}, "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ=="], + + "delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], + + "devalue": ["devalue@5.8.1", "", {}, "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + + "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], + + "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], + + "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + + "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + + "drizzle-kit": ["drizzle-kit@1.0.0-beta.22", "", { "dependencies": { "@drizzle-team/brocli": "^0.11.0", "@js-temporal/polyfill": "^0.5.1", "esbuild": "^0.25.10", "get-tsconfig": "^4.13.6", "jiti": "^2.6.1" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-9HTZuQRljQKTgCx4UhiGn8KYYfHGk4+B/bRR1714W67kz0qgJvdrG527i8rQD8uUyET9UTGR1u8syySJD4znGw=="], + + "drizzle-orm": ["drizzle-orm@1.0.0-beta.22", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@effect/sql": "^0.48.5", "@effect/sql-pg": "^0.49.7", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@sinclair/typebox": ">=0.34.8", "@sqlitecloud/drivers": ">=1.0.653", "@tidbcloud/serverless": "*", "@tursodatabase/database": ">=0.2.1", "@tursodatabase/database-common": ">=0.2.1", "@tursodatabase/database-wasm": ">=0.2.1", "@types/better-sqlite3": "*", "@types/mssql": "^9.1.4", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "arktype": ">=2.0.0", "better-sqlite3": ">=9.3.0", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "mssql": "^11.0.1", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5", "typebox": ">=1.0.0", "valibot": ">=1.0.0-beta.7", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@effect/sql", "@effect/sql-pg", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@sinclair/typebox", "@sqlitecloud/drivers", "@tidbcloud/serverless", "@tursodatabase/database", "@tursodatabase/database-common", "@tursodatabase/database-wasm", "@types/better-sqlite3", "@types/mssql", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "arktype", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "mssql", "mysql2", "pg", "postgres", "sql.js", "sqlite3", "typebox", "valibot", "zod"] }, "sha512-F+DZyVIvH0oVKa/w08Cle1xfoH+pc+htIXHG/frnMLG72aby9NYYr9oc+9XvghnoO4umxFItduz0OMmQJMnenw=="], + + "effect": ["effect@3.21.4", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-B89v/xSgPbl1J2Ai2u18jxq3odpFauU1rC6/eSs4FeNHi72kwKdJp12VGigvRV2lK+kRnx+OOz41XV8guZd4gQ=="], + + "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="], + + "embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="], + + "embla-carousel-svelte": ["embla-carousel-svelte@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "svelte": "^3.49.0 || ^4.0.0 || ^5.0.0" } }, "sha512-ZDsKk8Sdv+AUTygMYcwZjfRd1DTh+JSUzxkOo8b9iKAkYjg+39mzbY/lwHsE3jXSpKxdKWS69hPSNuzlOGtR2Q=="], + + "enhanced-resolve": ["enhanced-resolve@5.21.6", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ=="], + + "entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@10.5.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], + + "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@5.9.1", "", { "dependencies": { "@typescript-eslint/utils": "^8.61.0", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": "^8.45.0 || ^9.0.0 || ^10.0.0" } }, "sha512-30mHLNfEhzwaq5cquyWgnzrNXvT8AzwIwyeH5aj4U5ajhHSF2uiO6i09xpMDLv7koaZVTjLsvYF4m3gK/15tyA=="], + + "eslint-plugin-svelte": ["eslint-plugin-svelte@3.19.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", "globals": "^16.0.0", "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", "svelte-eslint-parser": "^1.7.0" }, "peerDependencies": { "eslint": "^8.57.1 || ^9.0.0 || ^10.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-t3rNaZeXz4d2gG4uJyMEYfJCFKf22+SWbSizIIXIWKu4wM+XPLiMWuSSr/C5821JmFeN9ogK+eExbG+z+twyxw=="], + + "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], + + "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], + + "esrap": ["esrap@2.2.12", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-On0QbLyaiAkVC4eXtgnXK9Kh2opit+3rcUSOc45DqJ2s/X2eXAHsGOKRSJ6IDagQEW5vPyivANfXUiqgXC67Rw=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "fast-check": ["fast-check@3.23.2", "", { "dependencies": { "pure-rand": "^6.1.0" } }, "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="], + + "fast-xml-builder": ["fast-xml-builder@1.2.0", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q=="], + + "fast-xml-parser": ["fast-xml-parser@5.9.3", "", { "dependencies": { "@nodable/entities": "^2.2.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^1.0.1", "path-expression-matcher": "^1.5.0", "strnum": "^2.4.1", "xml-naming": "^0.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-brCNCeScma/kqa54J4PIDriSSSLssRkuYaUCpvHJulGc3HGI/xxKUCTDcYkAdqJsyb//ydpbxecjC3hB9+tb/g=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="], + + "formsnap": ["formsnap@2.0.1", "", { "dependencies": { "svelte-toolbelt": "^0.5.0" }, "peerDependencies": { "svelte": "^5.0.0", "sveltekit-superforms": "^2.19.0" } }, "sha512-iJSe4YKd/W6WhLwKDVJU9FQeaJRpEFuolhju7ZXlRpUVyDdqFdMP8AUBICgnVvQPyP41IPAlBa/v0Eo35iE6wQ=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@17.6.0", "", {}, "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "html-to-text": ["html-to-text@10.0.0", "", { "dependencies": { "@selderee/plugin-htmlparser2": "~0.12.0", "deepmerge-ts": "^7.1.5", "dom-serializer": "^2.0.0", "htmlparser2": "^10.1.0", "selderee": "~0.12.0" } }, "sha512-2OH59Gtprdczel+7Rxgpz9hGVJREaf8Lt1H4kZwWHpEn70VQKRuMNGsb2eDbwaTzrYzb0hheiOG1P7Dim0B4dQ=="], + + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + + "htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="], + + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "human-id": ["human-id@4.2.0", "", { "bin": { "human-id": "dist/cli.js" } }, "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="], + + "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], + + "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], + + "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], + + "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + + "is-unsafe": ["is-unsafe@1.0.1", "", {}, "sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], + + "joi": ["joi@17.13.4", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-1RuuER6kmt8K8I3nIWvPZKi5RQCb568ZPyY4Pwjlua+yo+63ZTmIwxLZH0heBmiKN4uxjvCiarDrjaeH84xicQ=="], + + "jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="], + + "js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="], + + "js-levenshtein": ["js-levenshtein@1.1.6", "", {}, "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g=="], + + "js-sha256": ["js-sha256@0.11.1", "", {}, "sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + + "jsbi": ["jsbi@4.3.2", "", {}, "sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + + "known-css-properties": ["known-css-properties@0.37.0", "", {}, "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ=="], + + "kysely": ["kysely@0.28.17", "", {}, "sha512-nbD8lB9EB3wNdMhOCdx5Li8DxnLbvKByylRLcJ1h+4SkrowVeECAyZlyiKMThF7xFdRz0jSQ2MoJr+wXux2y0Q=="], + + "layerchart": ["layerchart@2.0.0-next.48", "", { "dependencies": { "@dagrejs/dagre": "^2.0.4", "@layerstack/svelte-actions": "1.0.1-next.18", "@layerstack/svelte-state": "0.1.0-next.23", "@layerstack/tailwind": "2.0.0-next.21", "@layerstack/utils": "2.0.0-next.18", "@types/d3-contour": "^3.0.6", "d3-array": "^3.2.4", "d3-chord": "^3.0.1", "d3-color": "^3.1.0", "d3-contour": "^4.0.2", "d3-delaunay": "^6.0.4", "d3-dsv": "^3.0.1", "d3-force": "^3.0.0", "d3-geo": "^3.1.1", "d3-geo-voronoi": "^2.1.0", "d3-hierarchy": "^3.1.2", "d3-interpolate": "^3.0.1", "d3-interpolate-path": "^2.3.0", "d3-path": "^3.1.0", "d3-quadtree": "^3.0.1", "d3-random": "^3.0.1", "d3-sankey": "^0.12.3", "d3-scale": "^4.0.2", "d3-scale-chromatic": "^3.1.0", "d3-shape": "^3.2.0", "d3-tile": "^1.0.0", "d3-time": "^3.1.0", "memoize": "^10.2.0", "runed": "^0.37.1" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-XoEYBztamA8lMxtF/Jz3aDX0HMk8dI+o4fK9fSl8ecT2Tdx3DQUjtKGtlQAOFdwC/AWifeLmKq5cMTQt9COZPQ=="], + + "leac": ["leac@0.7.0", "", {}, "sha512-qMrZeyEekgdRQ9o6a4NAB2EQZrv827GJdn1vnapwSJ90hWRB4TzUSunvacPkxQ2TnNqHNI1/zSt0hlo0crG8Jw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "libphonenumber-js": ["libphonenumber-js@1.13.7", "", {}, "sha512-rvr3HIMdOgzhz1RFGjftji+wjoAFlzhqCNqJOU/MKTZQ8d9NZxAR/tI+0weDicyoucqVR0U1GCniqHJ0f8aM2A=="], + + "libsql": ["libsql@0.5.29", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.29", "@libsql/darwin-x64": "0.5.29", "@libsql/linux-arm-gnueabihf": "0.5.29", "@libsql/linux-arm-musleabihf": "0.5.29", "@libsql/linux-arm64-gnu": "0.5.29", "@libsql/linux-arm64-musl": "0.5.29", "@libsql/linux-x64-gnu": "0.5.29", "@libsql/linux-x64-musl": "0.5.29", "@libsql/win32-x64-msvc": "0.5.29" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-8lMP8iMgiBzzoNbAPQ59qdVcj6UaE/Vnm+fiwX4doX4Narook0a4GPKWBEv+CR8a1OwbfkgL18uBfBjWdF0Fzg=="], + + "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], + + "lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="], + + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], + + "memoize": ["memoize@10.2.0", "", { "dependencies": { "mimic-function": "^5.0.1" } }, "sha512-DeC6b7QBrZsRs3Y02A6A7lQyzFbsQbqgjI6UW0GigGWV+u1s25TycMr0XHZE4cJce7rY/vyw2ctMQqfDkIhUEA=="], + + "memoize-weak": ["memoize-weak@1.0.2", "", {}, "sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + + "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + + "mode-watcher": ["mode-watcher@1.1.0", "", { "dependencies": { "runed": "^0.25.0", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.27.0" } }, "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g=="], + + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], + + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.14", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-U9kYi5bpVMEI31yC8iw4bJJp0avcHXA0W8/wNfLfnvJYzihQo2ZRPYPvpAAd570HAcCBjCTN7vnr+v4StKl1IQ=="], + + "nanostores": ["nanostores@1.3.0", "", {}, "sha512-XPUa/jz+P1oJvN9VBxw4L9MtdFfaH3DAryqPssqhb2kXjmb9npz0dly6rCsgFWOPr4Yg9mTfM3MDZgZZ+7A3lA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "natural-orderby": ["natural-orderby@5.0.0", "", {}, "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg=="], + + "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + + "node-rsa": ["node-rsa@1.1.1", "", { "dependencies": { "asn1": "^0.2.4" } }, "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw=="], + + "nodemailer": ["nodemailer@9.0.1", "", {}, "sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw=="], + + "normalize-url": ["normalize-url@8.1.1", "", {}, "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ=="], + + "obug": ["obug@2.1.3", "", {}, "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg=="], + + "ogl": ["ogl@1.0.11", "", {}, "sha512-kUpC154AFfxi16pmZUK4jk3J+8zxwTWGPo03EoYA8QPbzikHoaC82n6pNTbd+oEaJonaE8aPWBlX7ad9zrqLsA=="], + + "oniguruma-parser": ["oniguruma-parser@0.12.2", "", {}, "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw=="], + + "oniguruma-to-es": ["oniguruma-to-es@4.3.6", "", { "dependencies": { "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA=="], + + "openapi-fetch": ["openapi-fetch@0.17.0", "", { "dependencies": { "openapi-typescript-helpers": "^0.1.0" } }, "sha512-PsbZR1wAPcG91eEthKhN+Zn92FMHxv+/faECIwjXdxfTODGSGegYv0sc1Olz+HYPvKOuoXfp+0pA2XVt2cI0Ig=="], + + "openapi-typescript": ["openapi-typescript@7.13.0", "", { "dependencies": { "@redocly/openapi-core": "^1.34.6", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", "parse-json": "^8.3.0", "supports-color": "^10.2.2", "yargs-parser": "^21.1.1" }, "peerDependencies": { "typescript": "^5.x" }, "bin": { "openapi-typescript": "bin/cli.js" } }, "sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ=="], + + "openapi-typescript-helpers": ["openapi-typescript-helpers@0.1.0", "", {}, "sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "paneforge": ["paneforge@1.0.2", "", { "dependencies": { "runed": "^0.23.4", "svelte-toolbelt": "^0.9.2" }, "peerDependencies": { "svelte": "^5.29.0" } }, "sha512-KzmIXQH1wCfwZ4RsMohD/IUtEjVhteR+c+ulb/CHYJHX8SuDXoJmChtsc/Xs5Wl8NHS4L5Q7cxL8MG40gSU1bA=="], + + "parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="], + + "parse5": ["parse5@8.0.1", "", { "dependencies": { "entities": "^8.0.0" } }, "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw=="], + + "parseley": ["parseley@0.13.1", "", { "dependencies": { "leac": "^0.7.0", "peberminta": "^0.10.0" } }, "sha512-uNBJZzmb60l6p6VWLTmevizNAGnE0xoSf1n0B4q3ntegDNzcS68NRCcBDZTcyXHxt2XhBChsCuqj4M+nChvE/A=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-expression-matcher": ["path-expression-matcher@1.6.0", "", {}, "sha512-e5y7RCLHKjemsgQ4eqGJtPyr10ILz25HO7flzxhTV8bgvd5yHx98DGtCAtbVW9f2TqnYI/gEVZd+vz7snrdPTw=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "peberminta": ["peberminta@0.10.0", "", {}, "sha512-80B2AsU+I4Qdb0ZAPSfe9UwvGzwkM37IKIFEvdS3D/3Ndgv2bsuJ0bfG1+iEYO+l7Gfd4EUJmuRyq7efLgRMzQ=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + + "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], + + "postal-mime": ["postal-mime@2.7.4", "", {}, "sha512-0WdnFQYUrPGGTFu1uOqD2s7omwua8xaeYGdO6rb88oD5yJ/4pPHDA4sdWqfD8wQVfCny563n/HQS7zTFft+f/g=="], + + "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="], + + "postcss-load-config": ["postcss-load-config@3.1.4", "", { "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg=="], + + "postcss-safe-parser": ["postcss-safe-parser@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A=="], + + "postcss-scss": ["postcss-scss@4.0.9", "", { "peerDependencies": { "postcss": "^8.4.29" } }, "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A=="], + + "postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.8.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q=="], + + "prettier-plugin-svelte": ["prettier-plugin-svelte@4.1.1", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^5.0.0" } }, "sha512-wXvbXMjSvb4C9ENWTHXyd+ihakKCsJ6rJhLP6/8HFNj4GkZr48jqL9PoKsl2sk7SyCZRTnJ7O2TTowUpOxP/KA=="], + + "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.8.0", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-svelte"] }, "sha512-V8ITGH87yuBDF6JpEZTOVlUz/saAwqb8f3HRgUj8Lh+tGCcrmorhsLpYqzygwFwK0PE2Ib6Mv3M7T/uE2tZV1g=="], + + "promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="], + + "property-expr": ["property-expr@2.0.6", "", {}, "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="], + + "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="], + + "readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + + "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], + + "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], + + "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "resend": ["resend@6.14.0", "", { "dependencies": { "postal-mime": "2.7.4", "standardwebhooks": "1.0.0" }, "peerDependencies": { "@react-email/render": "*" }, "optionalPeers": ["@react-email/render"] }, "sha512-jVdpUgOoWGLjaP64lo8KwzHT9gY4w6Dl8c36CIb2F+ayYOMLr3khqs8xrNjXM2k19b+lPoj0VWQFhVNLiToBjA=="], + + "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="], + + "rolldown": ["rolldown@1.0.3", "", { "dependencies": { "@oxc-project/types": "=0.133.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.3", "@rolldown/binding-darwin-arm64": "1.0.3", "@rolldown/binding-darwin-x64": "1.0.3", "@rolldown/binding-freebsd-x64": "1.0.3", "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", "@rolldown/binding-linux-arm64-gnu": "1.0.3", "@rolldown/binding-linux-arm64-musl": "1.0.3", "@rolldown/binding-linux-ppc64-gnu": "1.0.3", "@rolldown/binding-linux-s390x-gnu": "1.0.3", "@rolldown/binding-linux-x64-gnu": "1.0.3", "@rolldown/binding-linux-x64-musl": "1.0.3", "@rolldown/binding-openharmony-arm64": "1.0.3", "@rolldown/binding-wasm32-wasi": "1.0.3", "@rolldown/binding-win32-arm64-msvc": "1.0.3", "@rolldown/binding-win32-x64-msvc": "1.0.3" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g=="], + + "rollup": ["rollup@4.62.2", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.62.2", "@rollup/rollup-android-arm64": "4.62.2", "@rollup/rollup-darwin-arm64": "4.62.2", "@rollup/rollup-darwin-x64": "4.62.2", "@rollup/rollup-freebsd-arm64": "4.62.2", "@rollup/rollup-freebsd-x64": "4.62.2", "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", "@rollup/rollup-linux-arm-musleabihf": "4.62.2", "@rollup/rollup-linux-arm64-gnu": "4.62.2", "@rollup/rollup-linux-arm64-musl": "4.62.2", "@rollup/rollup-linux-loong64-gnu": "4.62.2", "@rollup/rollup-linux-loong64-musl": "4.62.2", "@rollup/rollup-linux-ppc64-gnu": "4.62.2", "@rollup/rollup-linux-ppc64-musl": "4.62.2", "@rollup/rollup-linux-riscv64-gnu": "4.62.2", "@rollup/rollup-linux-riscv64-musl": "4.62.2", "@rollup/rollup-linux-s390x-gnu": "4.62.2", "@rollup/rollup-linux-x64-gnu": "4.62.2", "@rollup/rollup-linux-x64-musl": "4.62.2", "@rollup/rollup-openbsd-x64": "4.62.2", "@rollup/rollup-openharmony-arm64": "4.62.2", "@rollup/rollup-win32-arm64-msvc": "4.62.2", "@rollup/rollup-win32-ia32-msvc": "4.62.2", "@rollup/rollup-win32-x64-gnu": "4.62.2", "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA=="], + + "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], + + "runed": ["runed@0.37.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0", "zod": "^4.1.0" }, "optionalPeers": ["@sveltejs/kit", "zod"] }, "sha512-MeFY73xBW8IueWBm012nNFIGy19WUGPLtknavyUPMpnyt350M47PhGSGrGoSLbidwn+Zlt/O0cp8/OZE3LASWA=="], + + "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="], + + "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "samlify": ["samlify@2.13.1", "", { "dependencies": { "@authenio/xml-encryption": "^2.0.2", "@xmldom/xmldom": "^0.8.11", "node-rsa": "^1.1.1", "xml": "^1.0.1", "xml-crypto": "^6.1.2", "xml-escape": "^1.1.0", "xpath": "^0.0.34" } }, "sha512-vdYr/zohDGBbfWNU4miEzc1jmWOtkLySPViapC6nfGkv9KxzLq4UlGkKyryzwLw4jVlZk88Rw93HaCRVpe+t+g=="], + + "selderee": ["selderee@0.12.0", "", { "dependencies": { "parseley": "~0.13.1" } }, "sha512-b1YMh3+DHZp59DLna3qVwQ5iOla/nrI6mLBNW02XxU77M3046Df6VLkoaJyFz20VsGIG5kkp+FK0kg4K4HnUFw=="], + + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "set-cookie-parser": ["set-cookie-parser@3.1.0", "", {}, "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw=="], + + "shadcn-svelte": ["shadcn-svelte@1.3.0", "", { "dependencies": { "commander": "^14.0.0", "node-fetch-native": "^1.6.4", "postcss": "^8.5.5", "tailwind-merge": "^3.0.0" }, "peerDependencies": { "svelte": "^5.0.0" }, "bin": { "shadcn-svelte": "dist/index.mjs" } }, "sha512-Pd4ICWTkTks/b2YU4c9vF2XsX1x5HFPRl5bKszS1LcnWS83x+7T4WiIvbWz8Qh9knkcGZ+SCz1+Dmhdq+AYooA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "shiki": ["shiki@4.2.0", "", { "dependencies": { "@shikijs/core": "4.2.0", "@shikijs/engine-javascript": "4.2.0", "@shikijs/engine-oniguruma": "4.2.0", "@shikijs/langs": "4.2.0", "@shikijs/themes": "4.2.0", "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-hjNax6o/ylDy9lefQEaSDtzaT3iVNtZ3WmpQnbuQNoG4xvnSKf2kSKbihZVO4JRG1TTMejs7CmNRYlWgAL66pQ=="], + + "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + + "sqlite-wasm-kysely": ["sqlite-wasm-kysely@0.3.0", "", { "dependencies": { "@sqlite.org/sqlite-wasm": "^3.48.0-build2" }, "peerDependencies": { "kysely": "*" } }, "sha512-TzjBNv7KwRw6E3pdKdlRyZiTmUIE0UttT/Sl56MVwVARl/u5gp978KepazCJZewFUnlWHz9i3NQd4kOtP/Afdg=="], + + "standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="], + + "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], + + "superstruct": ["superstruct@2.0.2", "", {}, "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A=="], + + "supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "svelte": ["svelte@5.56.3", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", "esrap": "^2.2.11", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-w7JvrM5IFl5cmfbY0TLik9o7mjRUJmRMhOR51tBPu708Gr/MjbGs7VnJnr/B0CaXeI4vtnOh7RKxDr0cwhMdDA=="], + + "svelte-check": ["svelte-check@4.6.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "@sveltejs/load-config": "0.1.1", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-KhVnDFDSid57mmZtHz8gfW8AAGylOZ0vPnOIzVmAL+urzwK8sBYXRss953gD8T0OdgAQ11mdWhE6uadmtOz8TQ=="], + + "svelte-eslint-parser": ["svelte-eslint-parser@1.8.0", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0", "semver": "^7.7.2" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-mikR1qwIVy3t5WthUoAXkMwxkXvabZP9FJgdx35Ei7EbGWmctva1Pih16Koeor/bdNNq8NXHlwKGS6NkYTawLg=="], + + "svelte-sonner": ["svelte-sonner@1.1.1", "", { "dependencies": { "runed": "^0.28.0" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-5cd3p7wa4cq0NsqslMwdlPb7x1JglEZ/GKrLePWNr5bCxR1nagAVrY01FRFrXfUGs41miLt3C327+8XJo5BzZw=="], + + "svelte-themes": ["svelte-themes@2.0.10", "", { "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0" } }, "sha512-PlUXhJTm29o45DKi7l/iCvrjaHLXsy/HGmVR4RL4VnUwp86YZpTehPK5F5h8zk3oG7V0QFFR9BpsxPV+i40IoA=="], + + "svelte-toolbelt": ["svelte-toolbelt@0.10.6", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.35.1", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.30.2" } }, "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ=="], + + "sveltekit-superforms": ["sveltekit-superforms@2.30.1", "", { "dependencies": { "devalue": "^5.6.4", "memoize-weak": "^1.0.2", "ts-deepmerge": "^7.0.3" }, "optionalDependencies": { "@exodus/schemasafe": "^1.3.0", "@standard-schema/spec": "^1.1.0", "@typeschema/class-validator": "^0.3.0", "@valibot/to-json-schema": "^1.6.0", "@vinejs/vine": "^3.0.1", "arktype": "^2.2.0", "class-validator": "^0.14.4", "effect": "^3.21.0", "joi": "^17.13.3", "json-schema-to-ts": "^3.1.1", "superstruct": "^2.0.2", "typebox": "^1.1.6", "valibot": "^1.3.1", "yup": "^1.7.1", "zod": "^4.3.6", "zod-v3-to-json-schema": "^4.0.0" }, "peerDependencies": { "@sveltejs/kit": "1.x || 2.x", "svelte": "3.x || 4.x || >=5.0.0-next.51" } }, "sha512-wBzyqsE0idvEJWuNJ+HCiAtdxa7Z55GZ8jmtlVHJfonrk9bRYC49MoPaloYyFoYuU3QPy6Omna/Qzn1kaIkgew=="], + + "tabbable": ["tabbable@6.5.0", "", {}, "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA=="], + + "tailwind-merge": ["tailwind-merge@3.6.0", "", {}, "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w=="], + + "tailwind-variants": ["tailwind-variants@3.2.2", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge"] }, "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg=="], + + "tailwindcss": ["tailwindcss@4.3.1", "", {}, "sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q=="], + + "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], + + "tiny-case": ["tiny-case@1.0.3", "", {}, "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="], + + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], + + "tldts": ["tldts@6.1.86", "", { "dependencies": { "tldts-core": "^6.1.86" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ=="], + + "tldts-core": ["tldts-core@6.1.86", "", {}, "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA=="], + + "toposort": ["toposort@2.0.2", "", {}, "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="], + + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], + + "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], + + "ts-deepmerge": ["ts-deepmerge@7.0.3", "", {}, "sha512-Du/ZW2RfwV/D4cmA5rXafYjBQVuvu4qGiEEla4EmEHVHgRdx68Gftx7i66jn2bzHPwSVZY36Ae6OuDn9el4ZKA=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tsx": ["tsx@4.22.4", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg=="], + + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], + + "typebox": ["typebox@1.2.19", "", {}, "sha512-9stLVZhos9aUXJzu0Yf717xbcv3vFsE5APzsQ7j/honIUFtern451IdTlqmVzPzuGxHkeWwWc2cerw6m2lqKOQ=="], + + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], + + "typescript-eslint": ["typescript-eslint@8.61.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.61.1", "@typescript-eslint/parser": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/utils": "8.61.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-V7PayAfJokV3pEHgN7/v03D1SpujhRfQtYLbLIiBfDDncdg4PAiRBfoS4cnCANK4jmAPncczi59QO3afiXUlNw=="], + + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + + "unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], + + "uqr": ["uqr@0.1.3", "", {}, "sha512-0rjE8iEJe4YmT9TOhwsZtqCMRLc5DXZUI2UEYUUg63ikBkqqE5EYWaI0etFe/5KUcmcYwLih2RND1kq+hrUJXA=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "uri-js-replace": ["uri-js-replace@1.0.1", "", {}, "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g=="], + + "urlpattern-polyfill": ["urlpattern-polyfill@10.1.0", "", {}, "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="], + + "valibot": ["valibot@1.4.1", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-klCmFTz2jeDluy9RwX+F884TCiogtdBJ/YaxSx1EOBYXa3NXNWj8kR1jjN8rzluwojJVWWaHJ4r1U5LfICnM3g=="], + + "validator": ["validator@13.15.35", "", {}, "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw=="], + + "vaul-svelte": ["vaul-svelte@1.0.0-next.7", "", { "dependencies": { "runed": "^0.23.2", "svelte-toolbelt": "^0.7.1" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-7zN7Bi3dFQixvvbUJY9uGDe7Ws/dGZeBQR2pXdXmzQiakjrxBvWo0QrmsX3HK+VH+SZOltz378cmgmCS9f9rSg=="], + + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + + "vite": ["vite@8.0.16", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", "rolldown": "1.0.3", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw=="], + + "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], + + "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + + "xml": ["xml@1.0.1", "", {}, "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw=="], + + "xml-crypto": ["xml-crypto@6.1.2", "", { "dependencies": { "@xmldom/is-dom-node": "^1.0.1", "@xmldom/xmldom": "^0.8.10", "xpath": "^0.0.33" } }, "sha512-leBOVQdVi8FvPJrMYoum7Ici9qyxfE4kVi+AkpUoYCSXaQF4IlBm1cneTK9oAxR61LpYxTx7lNcsnBIeRpGW2w=="], + + "xml-escape": ["xml-escape@1.1.0", "", {}, "sha512-B/T4sDK8Z6aUh/qNr7mjKAwwncIljFuUP+DO/D5hloYFj+90O88z8Wf7oSucZTHxBAsC1/CTP4rtx/x1Uf72Mg=="], + + "xml-naming": ["xml-naming@0.1.0", "", {}, "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw=="], + + "xpath": ["xpath@0.0.34", "", {}, "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA=="], + + "yaml": ["yaml@1.10.3", "", {}, "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA=="], + + "yaml-ast-parser": ["yaml-ast-parser@0.0.43", "", {}, "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "yup": ["yup@1.7.1", "", { "dependencies": { "property-expr": "^2.0.5", "tiny-case": "^1.0.3", "toposort": "^2.0.2", "type-fest": "^2.19.0" } }, "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw=="], + + "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], + + "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "zod-v3-to-json-schema": ["zod-v3-to-json-schema@4.0.0", "", { "peerDependencies": { "zod": "^3.25 || ^4.0.14" } }, "sha512-KixLrhX/uPmRFnDgsZrzrk4x5SSJA+PmaE5adbfID9+3KPJcdxqRobaHU397EfWBqfQircrjKqvEqZ/mW5QH6w=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "@authenio/xml-encryption/xpath": ["xpath@0.0.32", "", {}, "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@inlang/paraglide-js/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "@redocly/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "@redocly/openapi-core/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], + + "@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], + + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.5", "", { "dependencies": { "@tybys/wasm-util": "^0.10.2" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q=="], + + "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], + + "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "bits-ui/runed": ["runed@0.35.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q=="], + + "d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], + + "d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="], + + "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="], + + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "eslint-plugin-svelte/globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="], + + "formsnap/svelte-toolbelt": ["svelte-toolbelt@0.5.0", "", { "dependencies": { "clsx": "^2.1.1", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0-next.126" } }, "sha512-t3tenZcnfQoIeRuQf/jBU7bvTeT3TGkcEE+1EUr5orp0lR7NEpprflpuie3x9Dn0W9nOKqs3HwKGJeeN5Ok1sQ=="], + + "htmlparser2/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + + "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "mode-watcher/runed": ["runed@0.25.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg=="], + + "mode-watcher/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="], + + "paneforge/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="], + + "paneforge/svelte-toolbelt": ["svelte-toolbelt@0.9.3", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.29.0", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.30.2" } }, "sha512-HCSWxCtVmv+c6g1ACb8LTwHVbDqLKJvHpo6J8TaqwUme2hj9ATJCpjCPNISR1OCq2Q4U1KT41if9ON0isINQZw=="], + + "svelte-check/chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + + "svelte-eslint-parser/eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "svelte-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "svelte-eslint-parser/espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "svelte-sonner/runed": ["runed@0.28.0", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ=="], + + "svelte-toolbelt/runed": ["runed@0.35.1", "", { "dependencies": { "dequal": "^2.0.3", "esm-env": "^1.0.0", "lz-string": "^1.5.0" }, "peerDependencies": { "@sveltejs/kit": "^2.21.0", "svelte": "^5.7.0" }, "optionalPeers": ["@sveltejs/kit"] }, "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q=="], + + "tsx/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + + "vaul-svelte/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="], + + "vaul-svelte/svelte-toolbelt": ["svelte-toolbelt@0.7.1", "", { "dependencies": { "clsx": "^2.1.1", "runed": "^0.23.2", "style-to-object": "^1.0.8" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ=="], + + "xml-crypto/xpath": ["xpath@0.0.33", "", {}, "sha512-NNXnzrkDrAzalLhIUc01jO2mOzXGXh1JwPgkihcLLzw98c0WgYDmmjSh1Kl3wzaxSVWMuA+fe0WTWOBDWCBmNA=="], + + "yup/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], + + "@redocly/openapi-core/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], + + "d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="], + + "d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="], + + "mode-watcher/svelte-toolbelt/runed": ["runed@0.23.4", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA=="], + + "paneforge/svelte-toolbelt/runed": ["runed@0.29.2", "", { "dependencies": { "esm-env": "^1.0.0" }, "peerDependencies": { "svelte": "^5.7.0" } }, "sha512-0cq6cA6sYGZwl/FvVqjx9YN+1xEBu9sDDyuWdDW1yWX7JF2wmvmVKfH+hVCZs+csW+P3ARH92MjI3H9QTagOQA=="], + + "svelte-check/chokidar/readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + + "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + + "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], + + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], + + "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], + + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], + + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], + + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + + "@redocly/openapi-core/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + } +} diff --git a/components.json b/components.json new file mode 100644 index 0000000..eaea37d --- /dev/null +++ b/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "tailwind": { + "css": "src/routes/layout.css", + "baseColor": "neutral" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils", + "ui": "$lib/components/ui", + "hooks": "$lib/hooks", + "lib": "$lib" + }, + "typescript": true, + "registry": "https://shadcn-svelte.com/registry", + "style": "nova", + "iconLibrary": "lucide", + "menuColor": "default", + "menuAccent": "subtle" +} diff --git a/config/oauth.json b/config/oauth.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/config/oauth.json @@ -0,0 +1 @@ +[] diff --git a/db.sqlite b/db.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..1e30078448efa7398ec25d916c59b63124a3023b GIT binary patch literal 94208 zcmeI*ON<-meE@KBSF06eNwnkG8^dr)$#or7=I*>7G6aP0=a9?yBQUt%yvQMkGvx5i zG$>Yf9V9?eptl4?a_K$CT-qLkUJ3*Vg5;1(PHlk(EqrMYY0+=UrFK`+YE{H3BKbek z4u>-z=bQiUd(3b+$C0OZ2#RwD}?!9EP;n_eR+59op-#S?2M6YYJH@13`-kr9^Z%*W1(^^ zP!5H&$JRRO#|O_$dYo7%dx)Ny%w1zFaJ0$jDDbuGz9U0D3XHY+IB-}@NugpRkcl-u z!1FEC*VaqiXSSni&QZXy##&o*0+n2

Hz<#&%D$PS%jimjk&?4rkBbri_w&L_ak7kLm{;%4Wr3a{wsuJPJBFW+N%jWos4#^>|;(nWclCVpC8 z>!n9`k6zu~Bj5HOdskVFaM`=0r$L>}dF^~IPo`VvaWem0Fh~BgIUq%`C)W5(4kvS7 zJ)gsq>DD=%%s-dI@!;m}-h1zPKYn-Bj?NbI+38y+Ih?eovy1TRp3$bxRD*S!+thov zB~6hzIcaf^+Jie^n-2`!lv-$f+WyYI4wobvYwCr|Cj<4u<=5}>x32DG-n*#5oeix; zo_*&3nDy=Mz43)9r!{ml8O`^YdK>sQWnJGj?0%+`8?G~9!2 zI;KrWqa$;qom-*NN9{8m+V7&~mWpGWXVxYo%ertg+~hbx3zyT#KItnr^G*u)Q2_4z z)3)5wEO!raQG9M<7x)a}X~(P@qk)MQtM+l4;QHP7Z(QB`@QsTK++AIZcE>m0f92AI zl$-Fz``0f`NV*AMdHCV(?%wU&-cLfSDsvj=>D0CJ)#r4AlwJmafEc*ZSyD?;Qo=`C=@U z$hkY$v;A|R7>mb>v0Nlp3apCq$lX^Q-F0^&(O5Qy4+A2hQX~|OUB63TySkUSeNn-k z$)7x(_I>=umEFC!-}Zj$U6G%3t0xaT=dn-wTwJdnp*(h2a9MBkwBvy@?e=$VcE+G} z?#N=(1X{RpTeyRCk7ORrdlbXjf;IXB&B5(()hEh}M=yD-JWntl72-)vX?;$G8N7OR zFZA|Bg}KR`I+?)lC7vfad6N9<$BV61see1QD)p0H-O0oD`BFdK4?d&RPZGJu6i>FX zfn!hco^5r+@#NBrn;2dxK1yhvsWEQJIhv05cAdv(%CfY;stQRULLhie*Ex}6XQ|LZFhLAmotil#Z5Y>f;PpWJHM z`GVku6*n<9#ws^jcL zila1z=0s9wHI0^KnPORurWlSAkf3QiOOOPCbXCEd^3jp-Xj5K_eAf5j2F&Xq^x^O(RKC z;Av9BXCr>_uYdN=e{42^5U~j7o<=uYJrm6?%HDndzjf`l$Ct(<7(f67KmY_l00cn5 z6?ph3TYgEpEv+>k=680I4TkB`3RSi1W0Ya?m2@br_PXO}muJO9WTrY|a$ag=lzL^L zhy^uNSccQZ5W^BuTelAz_@j!|6+XzkEG5n0BQ2ffDS}`)ou?Hf$`n2dWAQN=VnzAB zMlmX{iL|CDq{b-(Me4kw@i>7h3W%ZcF&d+&3e8h2PNM4qArm6Y;sYr~QwUz=L|If> zMG#~~QyHD0Sb-F1mX|dKA9*PZBk-JvRF+opVIRWBek_gGt00_#z)*tV{lUL~`pth> zkN=YPz9#W+Nq@n6{@T0aIc|7%cCumfuvyQ_hvj@+YYen7tw#pYe5Fih5>x`kNP-ku zniTNLNPLV-k|IZoZQE{}nz5iVjLLSWdVUZ|A&XEcif#5t-Z4haa5%R>l(>(GP?@%K z&0w|7^isiPZ07XRhjH7Eh11q}+C$Ccg734DNNku1qsdgM=4VVLM^laNh)qp;&dk=+ z2`5KsS!URX)f2_yG+u3lg{Bp>#6{oEwhr5KW_rlT<=kYH$_&%vrO_Ofx=A@#j~p6d zZWPXkOGYPIH{_xdj3J6_&Ui&p&7npYbgqa-nQA%OfRU?x~3uSyWKME-^`tu4kqCqGnla zkM4CtT%>~7^kH2oIlNe^h0R2hZDz;aWN}KMNV|~I z1JTA2YZLcjSa(m z&a%~Hai%QoX_kt283Tk_?}&yIx&3>uJ1xmT1;k zBHPbR<&qn2oLq(5O|eq6GS4mBOQ~F;v-M)HSyl+SR<)IGjL6ptbGchw=DKM|?Mk$g zFelB#z-%VN{cJxzQTSZg03KJaXIAzQXg{~T@u5DnZdA?l1 z`Lvl_)QzJ+V_G)Xl~^}jvqpAMZRUE7Q9bR*3wEGT@j;^!w&YrTAV(fKnXBhiTDz^#cA3zl^S$QiF95m7p+3SYE}}}x*Su(RU+n^PZ~AS zbhocuGjVeh+NF99Z^vrc4ApXkT2HT*qhyi5@p9RPI6~29$DO5O(?TU@~tx4|oTBzPMWm9~7yWM4d9LqpXn!4PNkDDbNf6rVtYG%jvMYTAA<8;e7u7K~PA5mK`vfiIAB>VlY#kb}ix zInFuxX{4$y@><30E`}K?71TPo;n$s{=CtWrq>Ov=?rauw=E@}OWI`&Jn3Btdoyd%s zSi{04EObJ}Xd|Yw(}cmu{pw-A*JpzfYgA*&nw=F3x#nzasqu_cF;ruiPDJ>j8I5XG zooQ87U7MMrLYT{Fp3#>5n$ljTO{JVxhpBu!KFpN*F`GyI2*m_5c5WgVW+5deyVGQ( zV~&hs%AAMi38c2`OQJa|rI}8poLewPBBwZVIG>+%%^Kg&^rKC#g)f2a%yC^4CQUBE z)+gn5x-H2_n$k*Y_`AN4WNNB+E?uU0lu)ebKqY7U|71nk1r$9@rjNPp8Ex>YXCpM*KSyb ziu3xb@BMl`zK-|nTmBz={6F^pYQ2kxF$jPF2!H?xfB*=900@8p2!H?xfWRM!z#nf* z-pkIzZ@s%M`7S#H?SB66^&fcfe;7aj1V8`;KmY_l00ck)1V8`;KmY{R0>?S;E7Fd% zv-9rpTaqV2hR2h(G8%>_1X(U0rW4bQo+Y&SINTob(X97}ul~(fcazFO(}t)}WqT6U zNJS^3x!=_KCZJgr@ZD1Iqm_0=}Ru5XZlOq}%g@)zZr@BXd9h_u`NK;nRPp z;vfJ5AOHd&00JNY0w4eaAOHd&@L~$MpZ{NWiUQvMznEnUTMYsr00JNY0w4eaAOHd& z00JNY0viGM{r_bbAGp{5#fUvH%>B~o*hVykb(N{nfhTy~}PjyNaiO62*EQ`>Hlw-P*Oa8vlBgNyyD-YaZ_4t44|K}GO z1hyRnKmY_l00ck)1V8`;KmY_l00h2B0&i}U-X||(*!s#g?|bTX8rS{5^=$e7#pC}B zk6-`+5C8!X009sH0T2KI5C8!X009tqp#^-~Z~4|=Yw&IFc~@Ux*unu_aex2c>;IMq z|AzqtKmY_l00ck)1V8`;KmY_l00e&j0uRUDYm)RyXlG}~h<4JcS&R`6B{@~mI>i!^ zO9}{u2`k!fQ)($09w*e?tlF^zQXt0pavmwgimfw+QYV>Wzj;SNrYR$(S1D%i+`qH= zEdt#^eQjntz5Rh>&lmfrU-Lgu(WoQa$WiZna7VFKt*SYOZfFjEb!a$~*(sGxuuMoV zDoVP;4wHPxsYga-o?^AUSs11(qf~SrQz+T7Vq!3@%L}P1W>Ud;vJqUQ5K6^+VX@XA zs7}#xa@}5VIu4fy#~$yl^bHAzESQ!tjOl~WWF||Yj@ZV}6Z3nEdf{G7Dn`c(qdY4boouKs4Yay5%`PM{Mv1*w5jxC5df@fGlR9JzE*tTiti_whFMvEHNXXROVk{2=*8@neW zdJ$p@w#-xMX!_vZ#H=53nbeqH40;`A$mwCOz;QDpIuMpt=#Uwvd+iEA4jnm_Y<9ZJ zQc+X2)Xbnti+C@i4!ZSXOlB#$MhytN?KqSwX3HsKq1P*q$3jy4I+(0?w{qJp7@pu{ zg5iju#?WezAxIJjqltLLk+`S?L@QMFFc&Ck&QxhSW)iE=p3PF_NTFa&B4$RHD#>JXN>c~-DkBs1(_%tpd(FOBZc_QBQPV?~twru-3Nx*m zO;;_Nj}6RdoG`o70zImC`USzNS5T=iAH|HvqalTLIJiUj$I9#fhtl~2Ef)9l|118F zJpNz$Kk|R-|Iy3a(LrP&00JNY0w4eaAOHd&00JNY0wC~v68PG7#rr&G)vmY+pXZd- zwwv&I&Yx_(zg_V?&v~Qu`~Tl~{J-`8r~fnmZ+=e_uv!oR0T2KI5C8!X009sH0T2KI Z5CDPyFM%uD9`6-*wC#?zwzoaL{{?Wg6vzMo literal 0 HcmV?d00001 diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..08c37b5 --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'drizzle-kit'; + +if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set'); + +export default defineConfig({ + dbCredentials: { url: process.env.DATABASE_URL }, + dialect: 'sqlite', + schema: './src/lib/server/db/schema.ts', + strict: true, + verbose: true +}); diff --git a/drizzle/20260621092126_real_klaw/migration.sql b/drizzle/20260621092126_real_klaw/migration.sql new file mode 100644 index 0000000..d0194e6 --- /dev/null +++ b/drizzle/20260621092126_real_klaw/migration.sql @@ -0,0 +1,70 @@ +CREATE TABLE `account` ( + `id` text PRIMARY KEY, + `account_id` text NOT NULL, + `provider_id` text NOT NULL, + `user_id` text NOT NULL, + `access_token` text, + `refresh_token` text, + `id_token` text, + `access_token_expires_at` integer, + `refresh_token_expires_at` integer, + `scope` text, + `password` text, + `created_at` integer NOT NULL, + `updated_at` integer NOT NULL, + CONSTRAINT `fk_account_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE +); +--> statement-breakpoint +CREATE TABLE `session` ( + `id` text PRIMARY KEY, + `expires_at` integer NOT NULL, + `token` text NOT NULL UNIQUE, + `created_at` integer NOT NULL, + `updated_at` integer NOT NULL, + `ip_address` text, + `user_agent` text, + `user_id` text NOT NULL, + `impersonated_by` text, + CONSTRAINT `fk_session_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE +); +--> statement-breakpoint +CREATE TABLE `two_factor` ( + `id` text PRIMARY KEY, + `secret` text NOT NULL, + `backup_codes` text NOT NULL, + `user_id` text NOT NULL, + `verified` integer DEFAULT true, + CONSTRAINT `fk_two_factor_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE +); +--> statement-breakpoint +CREATE TABLE `user` ( + `id` text PRIMARY KEY, + `name` text NOT NULL, + `email` text NOT NULL UNIQUE, + `email_verified` integer DEFAULT false NOT NULL, + `image` text, + `created_at` integer NOT NULL, + `updated_at` integer NOT NULL, + `role` text, + `banned` integer DEFAULT false, + `ban_reason` text, + `ban_expires` integer, + `two_factor_enabled` integer DEFAULT false, + `username` text UNIQUE, + `display_username` text +); +--> statement-breakpoint +CREATE TABLE `verification` ( + `id` text PRIMARY KEY, + `identifier` text NOT NULL, + `value` text NOT NULL, + `expires_at` integer NOT NULL, + `created_at` integer NOT NULL, + `updated_at` integer NOT NULL +); +--> statement-breakpoint +CREATE INDEX `account_userId_idx` ON `account` (`user_id`);--> statement-breakpoint +CREATE INDEX `session_userId_idx` ON `session` (`user_id`);--> statement-breakpoint +CREATE INDEX `twoFactor_secret_idx` ON `two_factor` (`secret`);--> statement-breakpoint +CREATE INDEX `twoFactor_userId_idx` ON `two_factor` (`user_id`);--> statement-breakpoint +CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`); \ No newline at end of file diff --git a/drizzle/20260621092126_real_klaw/snapshot.json b/drizzle/20260621092126_real_klaw/snapshot.json new file mode 100644 index 0000000..9cba711 --- /dev/null +++ b/drizzle/20260621092126_real_klaw/snapshot.json @@ -0,0 +1,688 @@ +{ + "version": "7", + "dialect": "sqlite", + "id": "422c3fd2-6456-4770-8ba8-0707c5a220b8", + "prevIds": [ + "00000000-0000-0000-0000-000000000000" + ], + "ddl": [ + { + "name": "account", + "entityType": "tables" + }, + { + "name": "session", + "entityType": "tables" + }, + { + "name": "two_factor", + "entityType": "tables" + }, + { + "name": "user", + "entityType": "tables" + }, + { + "name": "verification", + "entityType": "tables" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "account_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "provider_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token_expires_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token_expires_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "scope", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "password", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "expires_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "token", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ip_address", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_agent", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "impersonated_by", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "secret", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "backup_codes", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "true", + "generated": null, + "name": "verified", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "name", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "email", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "email_verified", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "image", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "role", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "banned", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ban_reason", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ban_expires", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "two_factor_enabled", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "username", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "display_username", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "identifier", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "value", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "expires_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "verification" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_account_user_id_user_id_fk", + "entityType": "fks", + "table": "account" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_session_user_id_user_id_fk", + "entityType": "fks", + "table": "session" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_two_factor_user_id_user_id_fk", + "entityType": "fks", + "table": "two_factor" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "account_pk", + "table": "account", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "session_pk", + "table": "session", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "two_factor_pk", + "table": "two_factor", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "user_pk", + "table": "user", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "verification_pk", + "table": "verification", + "entityType": "pks" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "account_userId_idx", + "entityType": "indexes", + "table": "account" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "session_userId_idx", + "entityType": "indexes", + "table": "session" + }, + { + "columns": [ + { + "value": "secret", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "twoFactor_secret_idx", + "entityType": "indexes", + "table": "two_factor" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "twoFactor_userId_idx", + "entityType": "indexes", + "table": "two_factor" + }, + { + "columns": [ + { + "value": "identifier", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "verification_identifier_idx", + "entityType": "indexes", + "table": "verification" + }, + { + "columns": [ + "token" + ], + "nameExplicit": false, + "name": "session_token_unique", + "entityType": "uniques", + "table": "session" + }, + { + "columns": [ + "email" + ], + "nameExplicit": false, + "name": "user_email_unique", + "entityType": "uniques", + "table": "user" + }, + { + "columns": [ + "username" + ], + "nameExplicit": false, + "name": "user_username_unique", + "entityType": "uniques", + "table": "user" + } + ], + "renames": [] +} \ No newline at end of file diff --git a/drizzle/20260621224643_moaning_logan/migration.sql b/drizzle/20260621224643_moaning_logan/migration.sql new file mode 100644 index 0000000..3aa7a3d --- /dev/null +++ b/drizzle/20260621224643_moaning_logan/migration.sql @@ -0,0 +1,8 @@ +CREATE TABLE `machines` ( + `host` text DEFAULT '127.0.0.1' NOT NULL, + `id` text PRIMARY KEY, + `name` text, + `order` integer UNIQUE, + `port` integer DEFAULT 9999 NOT NULL, + `token` text NOT NULL +); diff --git a/drizzle/20260621224643_moaning_logan/snapshot.json b/drizzle/20260621224643_moaning_logan/snapshot.json new file mode 100644 index 0000000..6c3ada3 --- /dev/null +++ b/drizzle/20260621224643_moaning_logan/snapshot.json @@ -0,0 +1,770 @@ +{ + "version": "7", + "dialect": "sqlite", + "id": "32f84774-44a1-4363-85d8-8b00b9de063f", + "prevIds": [ + "422c3fd2-6456-4770-8ba8-0707c5a220b8" + ], + "ddl": [ + { + "name": "account", + "entityType": "tables" + }, + { + "name": "machines", + "entityType": "tables" + }, + { + "name": "session", + "entityType": "tables" + }, + { + "name": "two_factor", + "entityType": "tables" + }, + { + "name": "user", + "entityType": "tables" + }, + { + "name": "verification", + "entityType": "tables" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token_expires_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "account_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "password", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "provider_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token_expires_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "scope", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": "'127.0.0.1'", + "generated": null, + "name": "host", + "entityType": "columns", + "table": "machines" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "machines" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "name", + "entityType": "columns", + "table": "machines" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "order", + "entityType": "columns", + "table": "machines" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": "9999", + "generated": null, + "name": "port", + "entityType": "columns", + "table": "machines" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "token", + "entityType": "columns", + "table": "machines" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "expires_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "impersonated_by", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ip_address", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "token", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_agent", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "backup_codes", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "secret", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "true", + "generated": null, + "name": "verified", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ban_expires", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "banned", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ban_reason", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "display_username", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "email", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "email_verified", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "image", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "name", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "role", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "two_factor_enabled", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "username", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "expires_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "identifier", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "value", + "entityType": "columns", + "table": "verification" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_account_user_id_user_id_fk", + "entityType": "fks", + "table": "account" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_session_user_id_user_id_fk", + "entityType": "fks", + "table": "session" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_two_factor_user_id_user_id_fk", + "entityType": "fks", + "table": "two_factor" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "account_pk", + "table": "account", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "machines_pk", + "table": "machines", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "session_pk", + "table": "session", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "two_factor_pk", + "table": "two_factor", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "user_pk", + "table": "user", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "verification_pk", + "table": "verification", + "entityType": "pks" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "account_userId_idx", + "entityType": "indexes", + "table": "account" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "session_userId_idx", + "entityType": "indexes", + "table": "session" + }, + { + "columns": [ + { + "value": "secret", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "twoFactor_secret_idx", + "entityType": "indexes", + "table": "two_factor" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "twoFactor_userId_idx", + "entityType": "indexes", + "table": "two_factor" + }, + { + "columns": [ + { + "value": "identifier", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "verification_identifier_idx", + "entityType": "indexes", + "table": "verification" + }, + { + "columns": [ + "order" + ], + "nameExplicit": false, + "name": "machines_order_unique", + "entityType": "uniques", + "table": "machines" + }, + { + "columns": [ + "token" + ], + "nameExplicit": false, + "name": "session_token_unique", + "entityType": "uniques", + "table": "session" + }, + { + "columns": [ + "email" + ], + "nameExplicit": false, + "name": "user_email_unique", + "entityType": "uniques", + "table": "user" + }, + { + "columns": [ + "username" + ], + "nameExplicit": false, + "name": "user_username_unique", + "entityType": "uniques", + "table": "user" + } + ], + "renames": [] +} \ No newline at end of file diff --git a/drizzle/20260621233631_silent_otto_octavius/migration.sql b/drizzle/20260621233631_silent_otto_octavius/migration.sql new file mode 100644 index 0000000..4026002 --- /dev/null +++ b/drizzle/20260621233631_silent_otto_octavius/migration.sql @@ -0,0 +1,3 @@ +ALTER TABLE `machines` ADD `address` text DEFAULT 'http://127.0.0.1:9999' NOT NULL;--> statement-breakpoint +ALTER TABLE `machines` DROP COLUMN `host`;--> statement-breakpoint +ALTER TABLE `machines` DROP COLUMN `port`; \ No newline at end of file diff --git a/drizzle/20260621233631_silent_otto_octavius/snapshot.json b/drizzle/20260621233631_silent_otto_octavius/snapshot.json new file mode 100644 index 0000000..710733f --- /dev/null +++ b/drizzle/20260621233631_silent_otto_octavius/snapshot.json @@ -0,0 +1,760 @@ +{ + "version": "7", + "dialect": "sqlite", + "id": "b3403d40-d4c3-4f1a-8d1d-763c548f5bc7", + "prevIds": [ + "32f84774-44a1-4363-85d8-8b00b9de063f" + ], + "ddl": [ + { + "name": "account", + "entityType": "tables" + }, + { + "name": "machines", + "entityType": "tables" + }, + { + "name": "session", + "entityType": "tables" + }, + { + "name": "two_factor", + "entityType": "tables" + }, + { + "name": "user", + "entityType": "tables" + }, + { + "name": "verification", + "entityType": "tables" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token_expires_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "account_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "password", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "provider_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token_expires_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "scope", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": "'http://127.0.0.1:9999'", + "generated": null, + "name": "address", + "entityType": "columns", + "table": "machines" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "machines" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "name", + "entityType": "columns", + "table": "machines" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "order", + "entityType": "columns", + "table": "machines" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "token", + "entityType": "columns", + "table": "machines" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "expires_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "impersonated_by", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ip_address", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "token", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_agent", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "backup_codes", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "secret", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "user_id", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "true", + "generated": null, + "name": "verified", + "entityType": "columns", + "table": "two_factor" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ban_expires", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "banned", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "ban_reason", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "display_username", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "email", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "email_verified", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "image", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "name", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "role", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": "false", + "generated": null, + "name": "two_factor_enabled", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "user" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "username", + "entityType": "columns", + "table": "user" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "created_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "expires_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "identifier", + "entityType": "columns", + "table": "verification" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "updated_at", + "entityType": "columns", + "table": "verification" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "value", + "entityType": "columns", + "table": "verification" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_account_user_id_user_id_fk", + "entityType": "fks", + "table": "account" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_session_user_id_user_id_fk", + "entityType": "fks", + "table": "session" + }, + { + "columns": [ + "user_id" + ], + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_two_factor_user_id_user_id_fk", + "entityType": "fks", + "table": "two_factor" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "account_pk", + "table": "account", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "machines_pk", + "table": "machines", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "session_pk", + "table": "session", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "two_factor_pk", + "table": "two_factor", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "user_pk", + "table": "user", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "verification_pk", + "table": "verification", + "entityType": "pks" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "account_userId_idx", + "entityType": "indexes", + "table": "account" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "session_userId_idx", + "entityType": "indexes", + "table": "session" + }, + { + "columns": [ + { + "value": "secret", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "twoFactor_secret_idx", + "entityType": "indexes", + "table": "two_factor" + }, + { + "columns": [ + { + "value": "user_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "twoFactor_userId_idx", + "entityType": "indexes", + "table": "two_factor" + }, + { + "columns": [ + { + "value": "identifier", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "verification_identifier_idx", + "entityType": "indexes", + "table": "verification" + }, + { + "columns": [ + "order" + ], + "nameExplicit": false, + "name": "machines_order_unique", + "entityType": "uniques", + "table": "machines" + }, + { + "columns": [ + "token" + ], + "nameExplicit": false, + "name": "session_token_unique", + "entityType": "uniques", + "table": "session" + }, + { + "columns": [ + "email" + ], + "nameExplicit": false, + "name": "user_email_unique", + "entityType": "uniques", + "table": "user" + }, + { + "columns": [ + "username" + ], + "nameExplicit": false, + "name": "user_username_unique", + "entityType": "uniques", + "table": "user" + } + ], + "renames": [] +} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..1a88ff1 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,42 @@ +import js from '@eslint/js'; +import prettier from 'eslint-config-prettier'; +import perfectionist from 'eslint-plugin-perfectionist'; +import svelte from 'eslint-plugin-svelte'; +import { defineConfig, includeIgnoreFile } from 'eslint/config'; +import globals from 'globals'; +import path from 'node:path'; +import ts from 'typescript-eslint'; +const gitignorePath = path.resolve(import.meta.dirname, '.gitignore'); + +export default defineConfig( + includeIgnoreFile(gitignorePath), + js.configs.recommended, + ts.configs.recommended, + svelte.configs.recommended, + prettier, + perfectionist.configs['recommended-alphabetical'], + svelte.configs.prettier, + { + languageOptions: { globals: { ...globals.browser, ...globals.node } }, + rules: { + // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects. + // see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors + 'no-undef': 'off' + } + }, + { + files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'], + languageOptions: { + parserOptions: { + extraFileExtensions: ['.svelte'], + parser: ts.parser, + projectService: true + } + } + }, + { + // Override or add rule settings here, such as: + // 'svelte/button-has-type': 'error' + rules: {} + } +); diff --git a/messages/en.json b/messages/en.json new file mode 100644 index 0000000..5bb2a2a --- /dev/null +++ b/messages/en.json @@ -0,0 +1,271 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "account": "Account", + "already_have_account": "Already have an account?", + "appname": "NadiЯ", + "back_to_login": "Back to login", + "backup_code": "Backup code", + "backup_codes_notice": "Store these somewhere safe. Each code works once if you lose your device.", + "backup_codes_title": "Save your backup codes", + "check_your_email": "Check your email", + "code": "Code", + "confirm_password": "Confirm password", + "continue_action": "Continue", + "create_account": "Create account", + "dashboard": "Dashboard", + "dashboard_architecture": "Architecture", + "dashboard_ascending": "Ascending", + "dashboard_clock": "Clock", + "dashboard_col_free": "Free", + "dashboard_col_ip": "IP", + "dashboard_col_method": "Method", + "dashboard_col_mount": "Mount", + "dashboard_col_name": "Name", + "dashboard_col_path": "Path", + "dashboard_col_sensor": "Sensor", + "dashboard_col_size": "Size", + "dashboard_col_status": "Status", + "dashboard_col_temp": "Temp", + "dashboard_col_time": "Time", + "dashboard_col_usage": "Usage", + "dashboard_col_user": "User", + "dashboard_cpu": "CPU", + "dashboard_cpu_detail": "{cores} cores · {current} ({min}–{max})", + "dashboard_descending": "Descending", + "dashboard_dns": "DNS", + "dashboard_free_of": "{free} free of {total}", + "dashboard_hardware_clock": "Hardware clock", + "dashboard_heatmap_less": "Less", + "dashboard_heatmap_more": "More", + "dashboard_heatmap_samples": "{count} samples", + "dashboard_interval_10s": "Every 10s", + "dashboard_interval_30s": "Every 30s", + "dashboard_interval_5s": "Every 5s", + "dashboard_interval_custom": "Custom", + "dashboard_interval_second": "Every second", + "dashboard_kernel": "Kernel", + "dashboard_keymap": "Keymap", + "dashboard_language": "Language", + "dashboard_load_average": "Load Average", + "dashboard_load_detail": "{loadPct}% of {cores}c · 5m {load5} · 15m {load15}", + "dashboard_local_time": "Local time", + "dashboard_locale": "Locale", + "dashboard_logical_cores": "{cores} logical cores", + "dashboard_memory": "Memory", + "dashboard_nameserver": "Nameserver", + "dashboard_network": "Network", + "dashboard_next": "Next", + "dashboard_none": "none", + "dashboard_nothing_to_show": "Nothing to show.", + "dashboard_not_synced": "Not synced", + "dashboard_os": "OS", + "dashboard_packages": "Packages", + "dashboard_pagination_info": "{start}–{end} of {total}", + "dashboard_prev": "Prev", + "dashboard_recent_activity": "Recent activity", + "dashboard_pause": "Pause auto-refresh", + "dashboard_refresh": "Refresh", + "dashboard_resume": "Resume auto-refresh", + "dashboard_search_placeholder": "Search", + "dashboard_seconds_abbreviation": "s", + "dashboard_since": "since {bootTime}", + "dashboard_status_down": "down", + "dashboard_status_up": "up", + "dashboard_storage": "Storage", + "dashboard_swap": "Swap {swapPct}%", + "dashboard_synchronized": "Synchronized", + "dashboard_syncing": "Syncing…", + "dashboard_system": "System", + "dashboard_temperatures": "Temperatures", + "dashboard_time": "Time", + "dashboard_timezone": "Timezone", + "dashboard_up_to_date": "up to date", + "dashboard_updates": "{count} updates", + "dashboard_uptime": "Uptime", + "dashboard_used_percent": "{used}% used", + "dashboard_utc": "UTC", + "download": "Download", + "email": "Email", + "email_complete_body": "Your account has been created. Choose a password to finish setting it up.", + "email_complete_button": "Set password", + "email_complete_heading": "Complete your registration", + "email_complete_subject": "Complete your registration", + "email_greeting": "Hi {name},", + "email_link_fallback": "If the button doesn't work, copy and paste this link into your browser:", + "email_otp_body": "Use this code to finish signing in:", + "email_otp_heading": "Your verification code", + "email_otp_ignore": "If you didn't try to sign in, you can safely ignore this email.", + "email_otp_subject": "Your verification code", + "email_placeholder": "admin@example.com", + "email_reset_body": "We received a request to reset the password for your account. Click the button below to choose a new password.", + "email_reset_button": "Reset password", + "email_reset_heading": "Reset your password", + "email_reset_ignore": "If you didn't request a password reset, you can safely ignore this email. Your password will remain unchanged.", + "email_reset_subject": "Reset your password", + "email_verify_body": "Click the button below to verify your email address and activate your account.", + "email_verify_button": "Verify email", + "email_verify_heading": "Verify your email", + "email_verify_ignore": "If you didn't create an account, you can safely ignore this email.", + "email_verify_subject": "Verify your email address", + "enter_password_to_continue": "Confirm your password to continue", + "errors_email_invalid": "Enter a valid email address", + "errors_generic": "An error occurred during this operation, please review Nadir Logs for more information.", + "errors_invalid_code": "Invalid or expired code, try again.", + "errors_address_invalid": "Enter a valid URL, e.g. http://127.0.0.1:9999", + "errors_non_empty": "This field is required", + "errors_password_too_short": "Password must be at least {min} characters", + "errors_password_weak": "Use upper- and lower-case letters and at least one number.", + "errors_passwords_no_match": "Passwords do not match", + "errors_username_too_short": "Username must be at least {min} characters", + "errors_wrong_credentials": "Wrong credentials, try again.", + "errors_unauthenticated": "Unauthenticated", + "errors_not_found": "This item has not been found", + "finish": "Finish", + "forbidden": "You are not allowed to this operation.", + "forgot_password": "Forgot your password?", + "forgot_password_description": "Enter your email and we'll send you a reset link.", + "forgot_password_title": "Forgot your password?", + "home": "Home", + "invalid_reset_link": "This link is invalid or has expired.", + "login": "Login", + "login_social_description": "You have to login to use this platform. Use your favorite social or your credentials", + "login_with": "Login with {social}", + "logout": "Logout", + "manual_entry_key": "Can't scan? Enter this key in your authenticator app manually:", + "name": "Name", + "name_placeholder": "Jane Doe", + "nav_admin": "Admin", + "nav_admin_config": "Config", + "nav_admin_config_desc": "Application-wide configuration.", + "nav_admin_users": "Users", + "nav_admin_users_desc": "Manage user accounts, roles and access.", + "cancel": "Cancel", + "delete": "Delete", + "edit": "Edit", + "machine_actions": "Server actions", + "machine_add": "Add server", + "machine_add_description": "Connect a new server to manage from this dashboard.", + "machine_delete_confirm": "This permanently removes \"{name}\" from the database. The connected server is not touched.", + "machine_delete_title": "Delete server?", + "machine_edit": "Edit server", + "machine_edit_description": "Update the connection details for this server.", + "machine_save_edit": "Save changes", + "machine_token_keep": "Leave blank to keep the current token.", + "machine_address": "Address", + "machine_address_placeholder": "http://127.0.0.1:9999", + "machine_name": "Name", + "machine_name_placeholder": "Production server", + "machine_none": "No servers yet.", + "machine_save": "Add server", + "machine_search_placeholder": "Search servers…", + "machine_token": "Token", + "machine_token_placeholder": "Agent bearer token", + "nav_dashboard_overview": "Overview", + "nav_dashboard_overview_desc": "System status at a glance.", + "pagination_next": "Next", + "pagination_page_of": "Page {page} of {pages}", + "pagination_previous": "Previous", + "nav_system": "System", + "nav_system_datetime": "Date & Time", + "nav_system_datetime_desc": "Clock, timezone and time synchronisation.", + "nav_system_localization": "Localization", + "nav_system_localization_desc": "Language, locale and region settings.", + "new_password": "New password", + "no_account": "No account yet?", + "or": "Or", + "password": "Password", + "password_hint": "At least 8 characters, mixing upper- and lower-case letters and a number.", + "privacy_policy": "Privacy Policy", + "remember_me": "Remember me", + "reset_link_sent": "If an account exists for that email, a reset link is on its way.", + "reset_password_action": "Update password", + "reset_password_description": "Choose a strong password you don't use anywhere else.", + "reset_password_title": "Set a new password", + "scan_qr": "Add this key to your authenticator app, then enter the generated code below.", + "send_reset_link": "Send reset link", + "setup_2fa_description": "Add an extra layer of security to your account.", + "setup_2fa_title": "Set up two-factor authentication", + "sign_up": "Sign up", + "sign_up_description": "Sign up with your email and a username.", + "sign_up_title": "Create your account", + "terms_notice": "By clicking continue, you agree to our Terms of Service and Privacy Policy.", + "trust_device": "Trust this device for 30 days", + "two_factor_description": "Enter the 6-digit code from your authenticator app.", + "two_factor_title": "Two-factor authentication", + "use_authenticator": "Use authenticator app", + "use_backup_code": "Use a backup code", + "username": "Username", + "username_placeholder": "admin", + "verification_sent": "We sent a verification link to {email}. Click it to activate your account.", + "verify": "Verify", + "verify_your_email": "You need to first verify your email address", + "welcome_back": "Welcome back", + "users_title": "Users", + "users_description": "Manage application users.", + "users_add": "Add User", + "users_create": "Create", + "users_edit": "Edit", + "users_delete": "Delete", + "users_ban": "Ban", + "users_unban": "Unban", + "users_search_placeholder": "Search by email…", + "users_rows_per_page": "Rows per page", + "users_role": "Role", + "users_role_user": "User", + "users_role_admin": "Admin", + "users_created_at": "Joined", + "users_status": "Status", + "users_banned": "Banned", + "users_active": "Active", + "users_actions": "Actions", + "users_create_title": "Create user", + "users_create_description": "Add a new user to the system.", + "users_edit_title": "Edit user", + "users_edit_description": "Update user details.", + "users_delete_confirm_title": "Delete user?", + "users_delete_confirm_description": "This permanently removes the user. Optionally ban the email to prevent re-registration.", + "users_delete_ban_email": "Also ban this email", + "users_ban_reason": "Reason (optional)", + "users_no_results": "No users found.", + "users_page_of": "Page {page} of {total}", + "users_prev": "Previous", + "users_next": "Next", + "users_saved": "User saved", + "users_created": "User created", + "users_deleted": "User deleted", + "users_ban_action_title": "Ban user?", + "cancel": "Cancel", + "users_filter": "Filter", + "users_filter_title": "Filter Users", + "users_filter_active": "Active", + "users_filter_active_hint": "Users with a recent session.", + "users_filter_joined": "Joined", + "users_filter_any_time": "Any Time", + "users_filter_24h": "Last 24h", + "users_filter_7d": "Last 7 days", + "users_filter_30d": "Last 30 days", + "users_filter_date_range": "Date Range", + "users_filter_date_from": "From", + "users_filter_date_to": "To", + "users_filter_email_verified": "Email verified only", + "users_filter_online_only": "Online users only", + "users_filter_online_hint": "Users with an active session.", + "users_filter_show_banned": "Show banned users", + "users_filter_display": "Display", + "users_filter_reset": "Reset All", + "users_filter_count": "{n} filters active", + "users_invite": "Invite", + "users_invite_title": "Invite user", + "users_invite_description": "Send an email invitation. The user sets their own password.", + "users_invited": "Invitation sent", + "users_pending": "Pending", + "users_pending_expires": "Invite expires {date}", + "users_pending_no_invite": "Email not verified", + "users_resend_invite": "Resend invite", + "settings": "Settings", + "theme": "Theme", + "theme_light": "Light", + "theme_dark": "Dark", + "theme_system": "System", + "language": "Language" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2c2b5ab --- /dev/null +++ b/package.json @@ -0,0 +1,80 @@ +{ + "name": "clean", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "bun --bun vite dev --host", + "build": "vite build", + "preview": "vite preview", + "prepare": "svelte-kit sync || echo ''", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check . && eslint .", + "format": "prettier --write .", + "db:push": "drizzle-kit push", + "db:generate": "drizzle-kit generate", + "db:migrate": "drizzle-kit migrate", + "db:studio": "drizzle-kit studio" + }, + "devDependencies": { + "@better-svelte-email/cli": "^2.1.1", + "@eslint/js": "^10.0.1", + "@fontsource-variable/geist": "^5.2.9", + "@inlang/paraglide-js": "^2.18.2", + "@internationalized/date": "^3.12.0", + "@libsql/client": "^0.17.3", + "@lucide/svelte": "^1.21.0", + "@sveltejs/adapter-node": "^5.5.4", + "@sveltejs/kit": "^2.63.0", + "@sveltejs/vite-plugin-svelte": "^7.1.2", + "@tailwindcss/vite": "^4.3.0", + "@tanstack/table-core": "^8.21.3", + "@types/bun": "^1.3.14", + "@types/node": "^24", + "@types/nodemailer": "^8.0.1", + "bits-ui": "^2.16.3", + "clsx": "^2.1.1", + "drizzle-kit": "^1.0.0-beta.22", + "drizzle-orm": "^1.0.0-beta.22", + "embla-carousel-svelte": "^8.6.0", + "eslint": "^10.4.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-perfectionist": "^5.9.1", + "eslint-plugin-svelte": "^3.19.0", + "formsnap": "^2.0.1", + "globals": "^17.6.0", + "layerchart": "2.0.0-next.48", + "mode-watcher": "^1.1.0", + "openapi-typescript": "^7.13.0", + "paneforge": "^1.0.2", + "prettier": "^3.8.3", + "prettier-plugin-svelte": "^4.1.0", + "prettier-plugin-tailwindcss": "^0.8.0", + "shadcn-svelte": "^1.3.0", + "svelte": "^5.56.1", + "svelte-check": "^4.6.0", + "svelte-sonner": "^1.1.0", + "sveltekit-superforms": "^2.30.0", + "tailwind-merge": "^3.5.0", + "tailwind-variants": "^3.2.2", + "tailwindcss": "^4.3.0", + "tw-animate-css": "^1.4.0", + "typescript": "^6.0.3", + "typescript-eslint": "^8.60.1", + "vaul-svelte": "^1.0.0-next.7", + "vite": "^8.0.16" + }, + "dependencies": { + "@better-auth/infra": "^0.2.14", + "@better-svelte-email/components": "^2.1.1", + "@better-svelte-email/server": "^2.1.1", + "better-auth": "^1.6.20", + "nodemailer": "^9.0.1", + "ogl": "^1.0.11", + "openapi-fetch": "^0.17.0", + "runed": "^0.37.1", + "uqr": "^0.1.3", + "valibot": "^1.4.1" + } +} diff --git a/project.inlang/settings.json b/project.inlang/settings.json new file mode 100644 index 0000000..526869f --- /dev/null +++ b/project.inlang/settings.json @@ -0,0 +1,12 @@ +{ + "$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"] +} diff --git a/src/app.d.ts b/src/app.d.ts new file mode 100644 index 0000000..cd91bb4 --- /dev/null +++ b/src/app.d.ts @@ -0,0 +1,23 @@ +// See https://svelte.dev/docs/kit/types#app.d.ts + +import type { auth } from '$lib/auth/server'; + +// for information about these interfaces +declare global { + type Auth = typeof auth.$Infer; + type Fetch = typeof fetch; + type Session = Auth['Session']['session']; + type User = Auth['Session']['user']; + namespace App { + // interface Error {} + interface Locals { + session: null | Session; + user: null | User; + } + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..e23ec34 --- /dev/null +++ b/src/app.html @@ -0,0 +1,20 @@ + + + + + + + + + + + %sveltekit.head% + + + +

%sveltekit.body%
+ + diff --git a/src/hooks.server.ts b/src/hooks.server.ts new file mode 100644 index 0000000..cf2f2b1 --- /dev/null +++ b/src/hooks.server.ts @@ -0,0 +1,58 @@ +import { type Handle, redirect } from '@sveltejs/kit'; +import { sequence } from '@sveltejs/kit/hooks'; +import { dev } from '$app/env'; +import { building } from '$app/environment'; +import { auth } from '$lib/auth/server'; +import { env } from '$lib/const/schema'; +import { getTextDirection } from '$lib/paraglide/runtime'; +import { paraglideMiddleware } from '$lib/paraglide/server'; +import { svelteKitHandler } from 'better-auth/svelte-kit'; + +const handleBetterAuth: Handle = async ({ event, resolve }) => { + const session = await auth.api.getSession({ + headers: event.request.headers + }); + + if (session) { + event.locals.session = session.session; + event.locals.user = session.user; + } else if ( + !event.url.pathname.startsWith('/auth') && + !event.url.pathname.startsWith('/api/auth') + ) { + redirect(307, '/auth/sign-in'); + } + if ( + env.ENABLE_2FA && + session?.user !== undefined && + 'twoFactorEnabled' in session.user && + session?.user.twoFactorEnabled !== true && + !event.url.pathname.startsWith('/auth') && + !event.url.pathname.startsWith('/api/auth') + ) + redirect(307, '/auth/setup-2fa'); + if (session?.user && 'twoFactorRedirect' in session.user) redirect(307, '/auth/2fa'); + if (dev && env.ORIGIN.startsWith('https:')) event.url.protocol = 'https:'; + if (event.url.pathname.startsWith('/admin')) { + const roles = (session?.user?.role ?? '') + .split(',') + .map((r) => r.trim()) + .filter(Boolean); + if (!roles.includes('admin')) redirect(307, '/dashboard'); + } + return svelteKitHandler({ auth, building, event, resolve }); +}; + +const handleParaglide: Handle = ({ event, resolve }) => + paraglideMiddleware(event.request, ({ locale, request }) => { + event.request = request; + + return resolve(event, { + transformPageChunk: ({ html }) => + html + .replace('%paraglide.lang%', locale) + .replace('%paraglide.dir%', getTextDirection(locale)) + }); + }); + +export const handle: Handle = sequence(handleBetterAuth, handleParaglide); diff --git a/src/hooks.ts b/src/hooks.ts new file mode 100644 index 0000000..3c2e7ab --- /dev/null +++ b/src/hooks.ts @@ -0,0 +1,5 @@ +import type { Reroute } from '@sveltejs/kit'; + +import { deLocalizeUrl } from '$lib/paraglide/runtime'; + +export const reroute: Reroute = (request) => deLocalizeUrl(request.url).pathname; diff --git a/src/lib/assets/favicon.svg b/src/lib/assets/favicon.svg new file mode 100644 index 0000000..852a2b0 --- /dev/null +++ b/src/lib/assets/favicon.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/src/lib/auth/client.ts b/src/lib/auth/client.ts new file mode 100644 index 0000000..f6525c8 --- /dev/null +++ b/src/lib/auth/client.ts @@ -0,0 +1,31 @@ +import { goto } from '$app/navigation'; +import { resolve } from '$app/paths'; +import { page } from '$app/state'; +import { env } from '$env/dynamic/public'; +import { createAuthClient } from 'better-auth/client'; +import { + adminClient, + genericOAuthClient, + inferAdditionalFields, + twoFactorClient, + usernameClient +} from 'better-auth/client/plugins'; + +export const getAuthClient = () => + createAuthClient({ + baseURL: env.PUBLIC_ORIGIN, + fetchOptions: { + customFetchImpl: page.data.fetch + }, + plugins: [ + adminClient(), + genericOAuthClient(), + twoFactorClient({ + onTwoFactorRedirect: async () => { + await goto(resolve('/auth/2fa')); + } + }), + usernameClient(), + inferAdditionalFields() + ] + }); diff --git a/src/lib/auth/schemas.ts b/src/lib/auth/schemas.ts new file mode 100644 index 0000000..f302e4b --- /dev/null +++ b/src/lib/auth/schemas.ts @@ -0,0 +1,93 @@ +import { v } from '$lib'; +import { m } from '$lib/paraglide/messages'; + +const username = v.pipe( + v.string(m.errors_non_empty()), + v.nonEmpty(m.errors_non_empty()), + v.minLength(3, m.errors_username_too_short({ min: 3 })) +); +const email = v.pipe( + v.string(m.errors_non_empty()), + v.nonEmpty(m.errors_non_empty()), + v.email(m.errors_email_invalid()) +); + +const password = v.pipe( + v.string(m.errors_non_empty()), + v.nonEmpty(m.errors_non_empty()), + v.minLength(8, m.errors_password_too_short({ min: 8 })) +); + +const newPassword = v.pipe( + v.string(m.errors_non_empty()), + v.nonEmpty(m.errors_non_empty()), + v.minLength(8, m.errors_password_too_short({ min: 8 })), + v.check((p) => /[a-z]/.test(p) && /[A-Z]/.test(p) && /\d/.test(p), m.errors_password_weak()) +); + +const confirm = v.pipe(v.string(m.errors_non_empty()), v.nonEmpty(m.errors_non_empty())); + +export const loginSchema = v.object({ + _password: password, + rememberMe: v.pipe( + v.optional(v.string(), 'no'), + v.transform((x) => x === 'yes') + ), + username +}); + +export const registerSchema = v.pipe( + v.object({ _confirm: confirm, _password: newPassword, email, username }), + v.forward( + v.partialCheck( + [['_password'], ['_confirm']], + (input) => input._password === input._confirm, + m.errors_passwords_no_match() + ), + ['_confirm'] + ) +); + +export const resetRequestSchema = v.object({ email }); + +export const resetPasswordSchema = v.pipe( + v.object({ _confirm: confirm, newPassword, token: v.string() }), + v.forward( + v.partialCheck( + [['newPassword'], ['_confirm']], + (input) => input.newPassword === input._confirm, + m.errors_passwords_no_match() + ), + ['_confirm'] + ) +); + +const role = v.picklist(['user', 'admin']); + +export const createUserSchema = v.object({ + _password: newPassword, + email, + name: v.pipe(v.string(m.errors_non_empty()), v.nonEmpty(m.errors_non_empty())), + role, + username +}); + +export const updateUserSchema = v.object({ + email, + id: v.pipe(v.string(), v.nonEmpty()), + name: v.pipe(v.string(m.errors_non_empty()), v.nonEmpty(m.errors_non_empty())), + role, + username +}); + +export const banUserSchema = v.object({ + banReason: v.optional(v.string(), ''), + id: v.pipe(v.string(), v.nonEmpty()) +}); + +export const inviteUserSchema = v.object({ + email, + name: v.optional(v.string(), ''), + role, + username: v.optional(v.string(), '') +}); diff --git a/src/lib/auth/server.ts b/src/lib/auth/server.ts new file mode 100644 index 0000000..2501a87 --- /dev/null +++ b/src/lib/auth/server.ts @@ -0,0 +1,106 @@ +import { dash } from '@better-auth/infra'; +import { getRequestEvent } from '$app/server'; +import { env } from '$lib/const/schema'; +import { m } from '$lib/paraglide/messages'; +import { db } from '$lib/server/db'; +import * as schema from '$lib/server/db/schema'; +import { emailer } from '$lib/server/emails'; +import { betterAuth } from 'better-auth'; +import { drizzleAdapter } from 'better-auth/adapters/drizzle'; +import { admin, twoFactor, username } from 'better-auth/plugins'; +import { genericOAuth, type GenericOAuthConfig } from 'better-auth/plugins/generic-oauth'; +import { sveltekitCookies } from 'better-auth/svelte-kit'; +import path from 'node:path'; +import { cwd } from 'node:process'; + +export const oauthConfig = (await Bun.file( + path.join(cwd(), 'config/oauth.json') +).json()) as GenericOAuthConfig[]; + +export const auth = betterAuth({ + basePath: '/api/auth', + baseURL: env.ORIGIN, + database: drizzleAdapter(db, { + provider: 'sqlite', + schema + }), + emailAndPassword: { + autoSignIn: false, + customSyntheticUser: ({ additionalFields, coreFields, id }) => ({ + ...coreFields, + banExpires: null, + banned: false, + banReason: null, + displayUsername: null, + role: 'user', + twoFactorEnabled: false, + username: null, + ...additionalFields, + id + }), + disableSignUp: env.DISABLE_SIGNUP || false, + enabled: env.ENABLE_EMAIL_AND_PASSWORD || true, + requireEmailVerification: true, + sendResetPassword: async ({ token, url, user }) => { + if (url.endsWith('reset-password')) await emailer.sendResetPassword({ token, url, user }); + + if (url.endsWith('complete-registration')) + await emailer.sendCompleteRegistration({ token, url, user }); + } + }, + emailVerification: { + autoSignInAfterVerification: true, + sendOnSignIn: true, + sendOnSignUp: true, + sendVerificationEmail: async ({ url, user }) => { + await emailer.sendVerificationEmail({ url, user }); + } + }, + plugins: [ + admin(), + dash(), + genericOAuth({ config: oauthConfig }), + twoFactor({ + issuer: m.appname(), + otpOptions: { + sendOTP: async ({ otp, user }) => { + await emailer.sendOtp({ otp, user }); + } + }, + totpOptions: { + period: 30 + } + }), + username(), + sveltekitCookies(getRequestEvent) + ], + rateLimit: { enabled: true }, + socialProviders: { + facebook: + (process.env.FACEBOOK_CLIENT_ID && { + clientId: process.env.FACEBOOK_CLIENT_ID as string, + clientSecret: process.env.FACEBOOK_CLIENT_SECRET as string + }) || + undefined, + github: + (process.env.GITHUB_CLIENT_ID && { + clientId: process.env.GITHUB_CLIENT_ID as string, + clientSecret: process.env.GITHUB_CLIENT_SECRET as string + }) || + undefined, + google: + (process.env.GOOGLE_CLIENT_ID && { + clientId: process.env.GOOGLE_CLIENT_ID as string, + clientSecret: process.env.GOOGLE_CLIENT_SECRET as string + }) || + undefined + }, + telemetry: { enabled: false }, + user: { + deleteUser: { + enabled: true + } + } +}); + +export type Auth = typeof auth; diff --git a/src/lib/components/blocks/app-controls.svelte b/src/lib/components/blocks/app-controls.svelte new file mode 100644 index 0000000..304f277 --- /dev/null +++ b/src/lib/components/blocks/app-controls.svelte @@ -0,0 +1,92 @@ + + +{#snippet localePicker()} + + + {#snippet child({ props })} + + {/snippet} + + + {#each locales as l (l)} + pickLocale(l)}>{labelOf(l)} + {/each} + + +{/snippet} + +{#snippet themePicker()} + + + {#snippet child({ props })} + + {/snippet} + + + setMode('light')}> + {m.theme_light()} + + setMode('dark')}> + {m.theme_dark()} + + setMode('system')}> + {m.theme_system()} + + + +{/snippet} + + + +
+ + + {#snippet child({ props })} + + {/snippet} + + + {@render localePicker()} + {@render themePicker()} + + +
diff --git a/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte b/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte new file mode 100644 index 0000000..bb4db41 --- /dev/null +++ b/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte @@ -0,0 +1,49 @@ + + + + + {#each crumbs as crumb, i (crumb.href)} + {@const last = i === crumbs.length - 1} + {#if i > 0} + + diff --git a/src/lib/components/blocks/sidebar/app-sidebar.svelte b/src/lib/components/blocks/sidebar/app-sidebar.svelte new file mode 100644 index 0000000..5dd45cf --- /dev/null +++ b/src/lib/components/blocks/sidebar/app-sidebar.svelte @@ -0,0 +1,234 @@ + + + + +{#snippet sectionContent(section: (typeof data.navMain)[number])} + {#if section.url === '/dashboard'} + + {:else} + {#each section.items as item (item.url)} + + {item.title()} + + {item.description()} + + + {/each} + {/if} +{/snippet} + + + + + + + + {#snippet child({ props })} + +
+ + {@html favicon} +
+
+ {m.appname()} +
+
+ {/snippet} +
+
+
+
+ + + + + {#each data.navMain as item (item.url)} + + + {#snippet tooltipContent()} + {item.title()} + {/snippet} + {#snippet child({ props })} + { + // On mobile, open the second drawer instead of navigating — + // lets the user pick a sub-item before committing to a route. + if (isMobile.current && !e.metaKey && !e.ctrlKey && e.button === 0) { + e.preventDefault(); + mobileSection = item; + } + }} + > + + {item.title()} + + {/snippet} + + + {/each} + + + + + + + +
+ + +
+ + + { + if (!v) mobileSection = null; + }} +> + + + {mobileSection?.title()} + +
+ {#if mobileSection} + {@render sectionContent(mobileSection)} + {/if} +
+
+
diff --git a/src/lib/components/blocks/sidebar/machines-nav.svelte b/src/lib/components/blocks/sidebar/machines-nav.svelte new file mode 100644 index 0000000..143725d --- /dev/null +++ b/src/lib/components/blocks/sidebar/machines-nav.svelte @@ -0,0 +1,184 @@ + + +{#snippet addForm()} +
addMachine.validate()} + {...addMachine.preflight(machineSchema).enhance(async ({ submit }) => { + try { + await submit(); + await listMachines({ page: pageNum, search }).refresh(); + open = false; + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + + {m.machine_name()} + + {#each addMachine.fields.name.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.machine_address()} + + {#each addMachine.fields.address.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.machine_token()} + + {#each addMachine.fields.token.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + +
+{/snippet} + +
+ + + {#if isMobile.current} + + + {#snippet child({ props })} + + {/snippet} + + + + {m.machine_add()} + {m.machine_add_description()} + +
{@render addForm()}
+
+
+ {:else} + + + {#snippet child({ props })} + + {/snippet} + + + + {m.machine_add()} + {m.machine_add_description()} + + {@render addForm()} + + + {/if} +
+ + + {@const data = await machines} + + + {#if data.pages > 1} +
+ + {m.pagination_page_of({ page: data.page, pages: data.pages })} + +
+ {/if} +
diff --git a/src/lib/components/blocks/sidebar/nav-user.svelte b/src/lib/components/blocks/sidebar/nav-user.svelte new file mode 100644 index 0000000..bfc431f --- /dev/null +++ b/src/lib/components/blocks/sidebar/nav-user.svelte @@ -0,0 +1,82 @@ + + + + + + + {#snippet child({ props })} + + + + {user.name.slice(0, 1)} + +
+ {user.name} + {user.email} +
+ +
+ {/snippet} +
+ + +
+ + + {user.name.slice(0, 1)} + +
+ {user.name} + {user.email} +
+
+
+ + + + + + {m.account()} + + + + { + const authClient = getAuthClient(); + await authClient.signOut(); + await invalidateAll(); + }} + > + + {m.logout()} + +
+
+
+
diff --git a/src/lib/components/blocks/trunk/trunk.svelte b/src/lib/components/blocks/trunk/trunk.svelte new file mode 100644 index 0000000..98934c9 --- /dev/null +++ b/src/lib/components/blocks/trunk/trunk.svelte @@ -0,0 +1,202 @@ + + +
+ {@render children?.()} +
+ + diff --git a/src/lib/components/dashboard/activity-panel.svelte b/src/lib/components/dashboard/activity-panel.svelte new file mode 100644 index 0000000..3a24e42 --- /dev/null +++ b/src/lib/components/dashboard/activity-panel.svelte @@ -0,0 +1,45 @@ + + + e.time, key: 'time', label: m.dashboard_col_time() }, + { get: (e) => e.status, key: 'status', label: m.dashboard_col_status() }, + { get: (e) => e.method, key: 'method', label: m.dashboard_col_method() }, + { get: (e) => e.path, key: 'path', label: m.dashboard_col_path() }, + { get: (e) => e.username, key: 'user', label: m.dashboard_col_user() } + ]} + search={(e, q) => + e.path.toLowerCase().includes(q) || + e.method.toLowerCase().includes(q) || + e.username.toLowerCase().includes(q) || + String(e.status).includes(q)} +> + {#snippet row(entry, i)} +
+ {entry.status} + {entry.method} + {entry.path} + + {fmtTime(entry.time)} +
+ {/snippet} +
diff --git a/src/lib/components/dashboard/cpu-heatmap.svelte b/src/lib/components/dashboard/cpu-heatmap.svelte new file mode 100644 index 0000000..c2ade84 --- /dev/null +++ b/src/lib/components/dashboard/cpu-heatmap.svelte @@ -0,0 +1,112 @@ + + + + +
+ + + + {m.dashboard_cpu()} +
+
+ +
+
+ {avgLoad}% +
+
+ {cpuModel} +
+
+ +
+ {#each cores as c (c.core)} +
+
+ {c.usage_pct.toFixed(0)}% +
+
+ {/each} +
+ +
+ {m.dashboard_cpu_detail({ + cores: logicalCpus, + current: ghz(currentMhz), + max: ghz(maxMhz), + min: ghz(minMhz) + })} +
+
+
diff --git a/src/lib/components/dashboard/data-panel.svelte b/src/lib/components/dashboard/data-panel.svelte new file mode 100644 index 0000000..6edd5b4 --- /dev/null +++ b/src/lib/components/dashboard/data-panel.svelte @@ -0,0 +1,138 @@ + + + + +
+ + + + {title} +
+
+ {#if search} +
+ + +
+ {/if} + (sortIdx = Number(v))} + > + {columns[sortIdx]?.label} + + {#each columns as col, i (col.key)} + {col.label} + {/each} + + + +
+
+ + {#each slice as item, i (i)} + {@render row(item, i)} + {:else} +

{m.dashboard_nothing_to_show()}

+ {/each} + {#if sorted.length > pageSize} +
+ {m.dashboard_pagination_info({ + end: Math.min(sorted.length, (page + 1) * pageSize), + start: page * pageSize + 1, + total: sorted.length + })} +
+ + +
+
+ {/if} +
+
diff --git a/src/lib/components/dashboard/format.ts b/src/lib/components/dashboard/format.ts new file mode 100644 index 0000000..5bc638b --- /dev/null +++ b/src/lib/components/dashboard/format.ts @@ -0,0 +1,61 @@ +// Single source of truth for the dashboard's data shaping + color semantics. + +// ponytail: GB (10^9), not GiB — fine for a monitoring readout +export const gb = (bytes: number) => (bytes / 1e9).toFixed(1) + ' GB'; +export const ghz = (mhz: number) => (mhz / 1000).toFixed(1) + ' GHz'; +export const pct = (used: number, total: number) => (total ? Math.round((used / total) * 100) : 0); + +export function uptime(seconds: number) { + const d = Math.floor(seconds / 86400); + const h = Math.floor((seconds % 86400) / 3600); + const m = Math.floor((seconds % 3600) / 60); + return [d && `${d}d`, h && `${h}h`, `${m}m`].filter(Boolean).join(' '); +} + +// first IPv4 (no colon), address only +export const ipv4 = (addrs: null | string[]) => addrs?.find((a) => !a.includes(':'))?.split('/')[0]; + +// TZ pinned to UTC so SSR (Node host TZ) and first client paint produce identical +// strings — the locale comes from paraglide, so it matches whatever the user picked. +// ponytail: swap timeZone to the browser's TZ post-mount if you want local time. +import { getLocale } from '$lib/paraglide/runtime'; + +const DT_FMT: Intl.DateTimeFormatOptions = { + day: '2-digit', + hour: '2-digit', + hour12: false, + minute: '2-digit', + month: '2-digit', + second: '2-digit', + timeZone: 'UTC', + year: 'numeric' +}; +const TIME_FMT: Intl.DateTimeFormatOptions = { + hour: '2-digit', + hour12: false, + minute: '2-digit', + second: '2-digit', + timeZone: 'UTC' +}; +export const fmtTime = (t: string) => new Date(t).toLocaleTimeString(getLocale(), TIME_FMT); +export const fmtDateTime = (t: string) => new Date(t).toLocaleString(getLocale(), DT_FMT); + +// severity → color. green healthy, amber warning, red critical. Used everywhere. +export const usageText = (p: number) => + p >= 90 ? 'text-red-500' : p >= 75 ? 'text-amber-500' : 'text-emerald-500'; +export const usageBar = (p: number) => + p >= 90 + ? '*:data-[slot=progress-indicator]:bg-red-500' + : p >= 75 + ? '*:data-[slot=progress-indicator]:bg-amber-500' + : '*:data-[slot=progress-indicator]:bg-emerald-500'; +export const tempText = (c: number) => + c >= 80 ? 'text-red-500' : c >= 65 ? 'text-amber-500' : 'text-emerald-500'; +export const statusPill = (s: number) => + s === 0 || s >= 500 + ? 'bg-red-500/15 text-red-500' + : s >= 400 + ? 'bg-amber-500/15 text-amber-600 dark:text-amber-500' + : s >= 300 + ? 'bg-blue-500/15 text-blue-500' + : 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-500'; diff --git a/src/lib/components/dashboard/kpi-card.svelte b/src/lib/components/dashboard/kpi-card.svelte new file mode 100644 index 0000000..3edd6cf --- /dev/null +++ b/src/lib/components/dashboard/kpi-card.svelte @@ -0,0 +1,39 @@ + + + + +
+ + + + {label} +
+
+ +
{value}
+ {#if detail}
{detail}
{/if} + {@render extra?.()} +
+
diff --git a/src/lib/components/dashboard/network-panel.svelte b/src/lib/components/dashboard/network-panel.svelte new file mode 100644 index 0000000..670fa82 --- /dev/null +++ b/src/lib/components/dashboard/network-panel.svelte @@ -0,0 +1,45 @@ + + + i.name, key: 'name', label: m.dashboard_col_name() }, + { get: (i) => ipv4(i.addresses) ?? '', key: 'ip', label: m.dashboard_col_ip() }, + { get: (i) => (i.up ? 0 : 1), key: 'status', label: m.dashboard_col_status() } + ]} +> + {#snippet row(iface, i)} +
+ {iface.name} + {ipv4(iface.addresses) ?? '—'} + + + {iface.up ? m.dashboard_status_up() : m.dashboard_status_down()} + +
+ {/snippet} +
diff --git a/src/lib/components/dashboard/storage-panel.svelte b/src/lib/components/dashboard/storage-panel.svelte new file mode 100644 index 0000000..9fdeb39 --- /dev/null +++ b/src/lib/components/dashboard/storage-panel.svelte @@ -0,0 +1,45 @@ + + + pct(d.used_bytes, d.total_bytes), key: 'usage', label: m.dashboard_col_usage() }, + { get: (d) => d.mountpoint, key: 'mount', label: m.dashboard_col_mount() }, + { get: (d) => d.free_bytes, key: 'free', label: m.dashboard_col_free() }, + { get: (d) => d.total_bytes, key: 'size', label: m.dashboard_col_size() } + ]} +> + {#snippet row(disk, i)} + {@const used = pct(disk.used_bytes, disk.total_bytes)} +
+
+ {disk.mountpoint} + {disk.filesystem} · {disk.fstype} +
+ +
+ {m.dashboard_used_percent({ used })} + {m.dashboard_free_of({ free: gb(disk.free_bytes), total: gb(disk.total_bytes) })} +
+
+ {/snippet} +
diff --git a/src/lib/components/dashboard/system-panel.svelte b/src/lib/components/dashboard/system-panel.svelte new file mode 100644 index 0000000..e68f335 --- /dev/null +++ b/src/lib/components/dashboard/system-panel.svelte @@ -0,0 +1,117 @@ + + +{#snippet field( + label: string, + value: string, + opts: { class: string; mono: boolean } = { class: '', mono: false } +)} +
+ {label} + {value} +
+{/snippet} + +{#snippet section(heading: string, body: Snippet)} +
+ {heading} + {@render body()} +
+{/snippet} + +{#snippet cpuBody()} + {@render field(m.dashboard_cpu(), cpu.model)} + {@render field( + m.dashboard_logical_cores({ cores: cpu.logical_cpus }), + `${ghz(cpu.min_mhz)}–${ghz(cpu.max_mhz)}`, + { class: '', mono: true } + )} +{/snippet} + +{#snippet osBody()} + {@render field(m.dashboard_kernel(), os.kernel, { class: '', mono: true })} + {@render field(m.dashboard_architecture(), os.architecture, { class: '', mono: true })} +{/snippet} + +{#snippet timeBody()} + {@render field(m.dashboard_timezone(), details.time!.timezone)} + {@render field( + m.dashboard_clock(), + details.time!.ntp_synchronized + ? m.dashboard_synchronized() + : details.time!.ntp + ? m.dashboard_syncing() + : m.dashboard_not_synced(), + { class: details.time!.ntp_synchronized ? 'text-emerald-500' : 'text-amber-500', mono: false } + )} + {@render field( + m.dashboard_hardware_clock(), + details.time!.local_rtc ? m.dashboard_local_time() : m.dashboard_utc() + )} +{/snippet} + +{#snippet localeBody()} + {@render field(m.dashboard_language(), details.locale!.lang, { class: '', mono: true })} + {@render field(m.dashboard_keymap(), details.locale!.vc_keymap || '—', { class: '', mono: true })} +{/snippet} + +{#snippet dnsBody()} + {#each details.dns ?? [] as server (server)} + {@render field(m.dashboard_nameserver(), server, { class: '', mono: true })} + {:else} + {@render field(m.dashboard_nameserver(), m.dashboard_none())} + {/each} +{/snippet} + +{#snippet updatesBody()} + {@render field( + details.updates!.manager, + details.updates!.count > 0 + ? m.dashboard_updates({ count: details.updates!.count }) + : m.dashboard_up_to_date(), + { class: details.updates!.count > 0 ? 'text-amber-500' : 'text-emerald-500', mono: false } + )} +{/snippet} + + + +
+ + + + {m.dashboard_system()} +
+
+ + {@render section(m.dashboard_cpu(), cpuBody)} + {@render section(m.dashboard_os(), osBody)} + {#if details.time}{@render section(m.dashboard_time(), timeBody)}{/if} + {#if details.locale}{@render section(m.dashboard_locale(), localeBody)}{/if} + {#if details.dns}{@render section(m.dashboard_dns(), dnsBody)}{/if} + {#if details.updates}{@render section(m.dashboard_packages(), updatesBody)}{/if} + +
diff --git a/src/lib/components/dashboard/temperature-panel.svelte b/src/lib/components/dashboard/temperature-panel.svelte new file mode 100644 index 0000000..938aa80 --- /dev/null +++ b/src/lib/components/dashboard/temperature-panel.svelte @@ -0,0 +1,38 @@ + + + t.celsius, key: 'temp', label: m.dashboard_col_temp() }, + { get: (t) => t.label, key: 'sensor', label: m.dashboard_col_sensor() } + ]} +> + {#snippet row(temp, i)} +
+ {temp.label} #{temp.n} + {temp.celsius.toFixed(1)} °C +
+ {/snippet} +
diff --git a/src/lib/components/dashboard/types.ts b/src/lib/components/dashboard/types.ts new file mode 100644 index 0000000..f0b1c1f --- /dev/null +++ b/src/lib/components/dashboard/types.ts @@ -0,0 +1,33 @@ +export type Disk = { + filesystem: string; + free_bytes: number; + fstype: string; + mountpoint: string; + total_bytes: number; + used_bytes: number; +}; + +export type LogEntry = { + method: string; + module: string; + path: string; + status: number; + time: string; + username: string; +}; + +export type NetIface = { + addresses: null | string[]; + mac: string; + name: string; + up: boolean; +}; + +export type SystemDetails = { + dns: null | string[]; + locale: { lang: string; vc_keymap: string } | null; + time: { local_rtc: boolean; ntp: boolean; ntp_synchronized: boolean; timezone: string } | null; + updates: { count: number; manager: string } | null; +}; + +export type Temp = { celsius: number; label: string }; diff --git a/src/lib/components/ui/accordion/accordion-content.svelte b/src/lib/components/ui/accordion/accordion-content.svelte new file mode 100644 index 0000000..4548d50 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion-content.svelte @@ -0,0 +1,27 @@ + + + +
+ {@render children?.()} +
+
diff --git a/src/lib/components/ui/accordion/accordion-item.svelte b/src/lib/components/ui/accordion/accordion-item.svelte new file mode 100644 index 0000000..3795167 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion-item.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/accordion/accordion-trigger.svelte b/src/lib/components/ui/accordion/accordion-trigger.svelte new file mode 100644 index 0000000..22e56f5 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion-trigger.svelte @@ -0,0 +1,38 @@ + + + + + {@render children?.()} + + + diff --git a/src/lib/components/ui/accordion/accordion.svelte b/src/lib/components/ui/accordion/accordion.svelte new file mode 100644 index 0000000..5b7db19 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/accordion/index.ts b/src/lib/components/ui/accordion/index.ts new file mode 100644 index 0000000..9940f82 --- /dev/null +++ b/src/lib/components/ui/accordion/index.ts @@ -0,0 +1,16 @@ +import Content from './accordion-content.svelte'; +import Item from './accordion-item.svelte'; +import Trigger from './accordion-trigger.svelte'; +import Root from './accordion.svelte'; + +export { + // + Root as Accordion, + Content as AccordionContent, + Item as AccordionItem, + Trigger as AccordionTrigger, + Content, + Item, + Root, + Trigger +}; diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte new file mode 100644 index 0000000..86a3f63 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte new file mode 100644 index 0000000..243cea5 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte new file mode 100644 index 0000000..366c051 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte @@ -0,0 +1,34 @@ + + + + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte new file mode 100644 index 0000000..c4b1c8f --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte new file mode 100644 index 0000000..36ea499 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte new file mode 100644 index 0000000..711f699 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte new file mode 100644 index 0000000..e2e47b2 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte new file mode 100644 index 0000000..7596183 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte new file mode 100644 index 0000000..dd3ac7d --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte new file mode 100644 index 0000000..258b12c --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte b/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte new file mode 100644 index 0000000..51a3da1 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/alert-dialog.svelte b/src/lib/components/ui/alert-dialog/alert-dialog.svelte new file mode 100644 index 0000000..cde7911 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/alert-dialog/index.ts b/src/lib/components/ui/alert-dialog/index.ts new file mode 100644 index 0000000..ee29ecf --- /dev/null +++ b/src/lib/components/ui/alert-dialog/index.ts @@ -0,0 +1,40 @@ +import Action from './alert-dialog-action.svelte'; +import Cancel from './alert-dialog-cancel.svelte'; +import Content from './alert-dialog-content.svelte'; +import Description from './alert-dialog-description.svelte'; +import Footer from './alert-dialog-footer.svelte'; +import Header from './alert-dialog-header.svelte'; +import Media from './alert-dialog-media.svelte'; +import Overlay from './alert-dialog-overlay.svelte'; +import Portal from './alert-dialog-portal.svelte'; +import Title from './alert-dialog-title.svelte'; +import Trigger from './alert-dialog-trigger.svelte'; +import Root from './alert-dialog.svelte'; + +export { + Action, + // + Root as AlertDialog, + Action as AlertDialogAction, + Cancel as AlertDialogCancel, + Content as AlertDialogContent, + Description as AlertDialogDescription, + Footer as AlertDialogFooter, + Header as AlertDialogHeader, + Media as AlertDialogMedia, + Overlay as AlertDialogOverlay, + Portal as AlertDialogPortal, + Title as AlertDialogTitle, + Trigger as AlertDialogTrigger, + Cancel, + Content, + Description, + Footer, + Header, + Media, + Overlay, + Portal, + Root, + Title, + Trigger +}; diff --git a/src/lib/components/ui/alert/alert-action.svelte b/src/lib/components/ui/alert/alert-action.svelte new file mode 100644 index 0000000..4f1411a --- /dev/null +++ b/src/lib/components/ui/alert/alert-action.svelte @@ -0,0 +1,21 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert/alert-description.svelte b/src/lib/components/ui/alert/alert-description.svelte new file mode 100644 index 0000000..782c6d4 --- /dev/null +++ b/src/lib/components/ui/alert/alert-description.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/alert/alert-title.svelte b/src/lib/components/ui/alert/alert-title.svelte new file mode 100644 index 0000000..adc3d2d --- /dev/null +++ b/src/lib/components/ui/alert/alert-title.svelte @@ -0,0 +1,24 @@ + + +
svg]/alert:col-start-2 [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3', + className + )} + {...restProps} +> + {@render children?.()} +
diff --git a/src/lib/components/ui/alert/alert.svelte b/src/lib/components/ui/alert/alert.svelte new file mode 100644 index 0000000..4e27259 --- /dev/null +++ b/src/lib/components/ui/alert/alert.svelte @@ -0,0 +1,45 @@ + + + + + diff --git a/src/lib/components/ui/alert/index.ts b/src/lib/components/ui/alert/index.ts new file mode 100644 index 0000000..3cc1dcb --- /dev/null +++ b/src/lib/components/ui/alert/index.ts @@ -0,0 +1,17 @@ +import Action from './alert-action.svelte'; +import Description from './alert-description.svelte'; +import Title from './alert-title.svelte'; +import Root from './alert.svelte'; +export { type AlertVariant, alertVariants } from './alert.svelte'; + +export { + Action, + // + Root as Alert, + Action as AlertAction, + Description as AlertDescription, + Title as AlertTitle, + Description, + Root, + Title +}; diff --git a/src/lib/components/ui/aspect-ratio/aspect-ratio.svelte b/src/lib/components/ui/aspect-ratio/aspect-ratio.svelte new file mode 100644 index 0000000..1df5d5d --- /dev/null +++ b/src/lib/components/ui/aspect-ratio/aspect-ratio.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/aspect-ratio/index.ts b/src/lib/components/ui/aspect-ratio/index.ts new file mode 100644 index 0000000..61924de --- /dev/null +++ b/src/lib/components/ui/aspect-ratio/index.ts @@ -0,0 +1,3 @@ +import Root from './aspect-ratio.svelte'; + +export { Root as AspectRatio, Root }; diff --git a/src/lib/components/ui/avatar/avatar-badge.svelte b/src/lib/components/ui/avatar/avatar-badge.svelte new file mode 100644 index 0000000..8d56ba9 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-badge.svelte @@ -0,0 +1,27 @@ + + +svg]:hidden', + 'group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2', + 'group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2', + className + )} + {...restProps} +> + {@render children?.()} + diff --git a/src/lib/components/ui/avatar/avatar-fallback.svelte b/src/lib/components/ui/avatar/avatar-fallback.svelte new file mode 100644 index 0000000..f21a808 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-fallback.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/avatar/avatar-group-count.svelte b/src/lib/components/ui/avatar/avatar-group-count.svelte new file mode 100644 index 0000000..cd7b2e9 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-group-count.svelte @@ -0,0 +1,24 @@ + + +
svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3 ring-background relative flex shrink-0 items-center justify-center ring-2', + className + )} + {...restProps} +> + {@render children?.()} +
diff --git a/src/lib/components/ui/avatar/avatar-group.svelte b/src/lib/components/ui/avatar/avatar-group.svelte new file mode 100644 index 0000000..0d5c432 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-group.svelte @@ -0,0 +1,24 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/avatar/avatar-image.svelte b/src/lib/components/ui/avatar/avatar-image.svelte new file mode 100644 index 0000000..2e47594 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-image.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/avatar/avatar.svelte b/src/lib/components/ui/avatar/avatar.svelte new file mode 100644 index 0000000..5ae8641 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar.svelte @@ -0,0 +1,26 @@ + + + diff --git a/src/lib/components/ui/avatar/index.ts b/src/lib/components/ui/avatar/index.ts new file mode 100644 index 0000000..fa5112b --- /dev/null +++ b/src/lib/components/ui/avatar/index.ts @@ -0,0 +1,22 @@ +import Badge from './avatar-badge.svelte'; +import Fallback from './avatar-fallback.svelte'; +import GroupCount from './avatar-group-count.svelte'; +import Group from './avatar-group.svelte'; +import Image from './avatar-image.svelte'; +import Root from './avatar.svelte'; + +export { + // + Root as Avatar, + Badge as AvatarBadge, + Fallback as AvatarFallback, + Group as AvatarGroup, + GroupCount as AvatarGroupCount, + Image as AvatarImage, + Badge, + Fallback, + Group, + GroupCount, + Image, + Root +}; diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte new file mode 100644 index 0000000..b928c31 --- /dev/null +++ b/src/lib/components/ui/badge/badge.svelte @@ -0,0 +1,51 @@ + + + + + + {@render children?.()} + diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts new file mode 100644 index 0000000..4c25aea --- /dev/null +++ b/src/lib/components/ui/badge/index.ts @@ -0,0 +1,2 @@ +export { default as Badge } from './badge.svelte'; +export { type BadgeVariant, badgeVariants } from './badge.svelte'; diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte new file mode 100644 index 0000000..fe8ceff --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte @@ -0,0 +1,24 @@ + + + diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte new file mode 100644 index 0000000..2bb75c7 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte @@ -0,0 +1,21 @@ + + +
  • + {@render children?.()} +
  • diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte new file mode 100644 index 0000000..2077f2d --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte @@ -0,0 +1,32 @@ + + +{#if child} + {@render child({ props: attrs })} +{:else} + + {@render children?.()} + +{/if} diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte new file mode 100644 index 0000000..4971072 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte @@ -0,0 +1,24 @@ + + +
      + {@render children?.()} +
    diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte new file mode 100644 index 0000000..35da0f1 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte @@ -0,0 +1,24 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte b/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte new file mode 100644 index 0000000..7111db1 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte @@ -0,0 +1,28 @@ + + + diff --git a/src/lib/components/ui/breadcrumb/breadcrumb.svelte b/src/lib/components/ui/breadcrumb/breadcrumb.svelte new file mode 100644 index 0000000..3a30172 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/components/ui/breadcrumb/index.ts b/src/lib/components/ui/breadcrumb/index.ts new file mode 100644 index 0000000..e6601cf --- /dev/null +++ b/src/lib/components/ui/breadcrumb/index.ts @@ -0,0 +1,25 @@ +import Ellipsis from './breadcrumb-ellipsis.svelte'; +import Item from './breadcrumb-item.svelte'; +import Link from './breadcrumb-link.svelte'; +import List from './breadcrumb-list.svelte'; +import Page from './breadcrumb-page.svelte'; +import Separator from './breadcrumb-separator.svelte'; +import Root from './breadcrumb.svelte'; + +export { + // + Root as Breadcrumb, + Ellipsis as BreadcrumbEllipsis, + Item as BreadcrumbItem, + Link as BreadcrumbLink, + List as BreadcrumbList, + Page as BreadcrumbPage, + Separator as BreadcrumbSeparator, + Ellipsis, + Item, + Link, + List, + Page, + Root, + Separator +}; diff --git a/src/lib/components/ui/button-group/button-group-separator.svelte b/src/lib/components/ui/button-group/button-group-separator.svelte new file mode 100644 index 0000000..d426b13 --- /dev/null +++ b/src/lib/components/ui/button-group/button-group-separator.svelte @@ -0,0 +1,24 @@ + + + diff --git a/src/lib/components/ui/button-group/button-group-text.svelte b/src/lib/components/ui/button-group/button-group-text.svelte new file mode 100644 index 0000000..306a3e1 --- /dev/null +++ b/src/lib/components/ui/button-group/button-group-text.svelte @@ -0,0 +1,32 @@ + + +{#if child} + {@render child({ props: mergedProps })} +{:else} +
    + {@render mergedProps.children?.()} +
    +{/if} diff --git a/src/lib/components/ui/button-group/button-group.svelte b/src/lib/components/ui/button-group/button-group.svelte new file mode 100644 index 0000000..fee269d --- /dev/null +++ b/src/lib/components/ui/button-group/button-group.svelte @@ -0,0 +1,47 @@ + + + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/button-group/index.ts b/src/lib/components/ui/button-group/index.ts new file mode 100644 index 0000000..71ad857 --- /dev/null +++ b/src/lib/components/ui/button-group/index.ts @@ -0,0 +1,15 @@ +import Separator from './button-group-separator.svelte'; +import Text from './button-group-text.svelte'; +import Root, { type ButtonGroupOrientation, buttonGroupVariants } from './button-group.svelte'; + +export { + // + Root as ButtonGroup, + type ButtonGroupOrientation, + Separator as ButtonGroupSeparator, + Text as ButtonGroupText, + buttonGroupVariants, + Root, + Separator, + Text +}; diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte new file mode 100644 index 0000000..6285713 --- /dev/null +++ b/src/lib/components/ui/button/button.svelte @@ -0,0 +1,92 @@ + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts new file mode 100644 index 0000000..c91ac0b --- /dev/null +++ b/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants +} from './button.svelte'; + +export { + // + Root as Button, + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, + type ButtonProps as Props, + Root +}; diff --git a/src/lib/components/ui/calendar/calendar-caption.svelte b/src/lib/components/ui/calendar/calendar-caption.svelte new file mode 100644 index 0000000..b933d14 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-caption.svelte @@ -0,0 +1,79 @@ + + +{#snippet MonthSelect()} + { + if (!placeholder) return; + const v = Number.parseInt(e.currentTarget.value); + const newPlaceholder = placeholder.set({ month: v }); + placeholder = newPlaceholder.subtract({ months: monthIndex }); + }} + /> +{/snippet} + +{#snippet YearSelect()} + +{/snippet} + +{#if captionLayout === 'dropdown'} + {@render MonthSelect()} + {@render YearSelect()} +{:else if captionLayout === 'dropdown-months'} + {@render MonthSelect()} + {#if placeholder} + {formatYear(placeholder)} + {/if} +{:else if captionLayout === 'dropdown-years'} + {#if placeholder} + {formatMonth(placeholder)} + {/if} + {@render YearSelect()} +{:else} + {formatMonth(month)} {formatYear(month)} +{/if} diff --git a/src/lib/components/ui/calendar/calendar-cell.svelte b/src/lib/components/ui/calendar/calendar-cell.svelte new file mode 100644 index 0000000..ad32da9 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-cell.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-day.svelte b/src/lib/components/ui/calendar/calendar-day.svelte new file mode 100644 index 0000000..172b7e1 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-day.svelte @@ -0,0 +1,33 @@ + + +span]:text-xs [&>span]:opacity-70', + className + )} + {...restProps} +/> diff --git a/src/lib/components/ui/calendar/calendar-grid-body.svelte b/src/lib/components/ui/calendar/calendar-grid-body.svelte new file mode 100644 index 0000000..dfa76ec --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-body.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-grid-head.svelte b/src/lib/components/ui/calendar/calendar-grid-head.svelte new file mode 100644 index 0000000..9066d61 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-head.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-grid-row.svelte b/src/lib/components/ui/calendar/calendar-grid-row.svelte new file mode 100644 index 0000000..48ebe16 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-row.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-grid.svelte b/src/lib/components/ui/calendar/calendar-grid.svelte new file mode 100644 index 0000000..6b56e4d --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-head-cell.svelte b/src/lib/components/ui/calendar/calendar-head-cell.svelte new file mode 100644 index 0000000..fa007bd --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-head-cell.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-header.svelte b/src/lib/components/ui/calendar/calendar-header.svelte new file mode 100644 index 0000000..d0e0037 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-header.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-heading.svelte b/src/lib/components/ui/calendar/calendar-heading.svelte new file mode 100644 index 0000000..fdc0566 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-heading.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-month-select.svelte b/src/lib/components/ui/calendar/calendar-month-select.svelte new file mode 100644 index 0000000..3bd0fc0 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-month-select.svelte @@ -0,0 +1,48 @@ + + + + + {#snippet child({ monthItems, props, selectedMonthItem })} + + + {/snippet} + + diff --git a/src/lib/components/ui/calendar/calendar-month.svelte b/src/lib/components/ui/calendar/calendar-month.svelte new file mode 100644 index 0000000..087fd70 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-month.svelte @@ -0,0 +1,16 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/calendar/calendar-months.svelte b/src/lib/components/ui/calendar/calendar-months.svelte new file mode 100644 index 0000000..5f65aed --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-months.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/calendar/calendar-nav.svelte b/src/lib/components/ui/calendar/calendar-nav.svelte new file mode 100644 index 0000000..e4d8069 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-nav.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-next-button.svelte b/src/lib/components/ui/calendar/calendar-next-button.svelte new file mode 100644 index 0000000..9db2a7a --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-next-button.svelte @@ -0,0 +1,36 @@ + + +{#snippet Fallback()} + +{/snippet} + + + {#if children} + {@render children?.()} + {:else} + {@render Fallback()} + {/if} + diff --git a/src/lib/components/ui/calendar/calendar-prev-button.svelte b/src/lib/components/ui/calendar/calendar-prev-button.svelte new file mode 100644 index 0000000..db09d62 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-prev-button.svelte @@ -0,0 +1,36 @@ + + +{#snippet Fallback()} + +{/snippet} + + + {#if children} + {@render children?.()} + {:else} + {@render Fallback()} + {/if} + diff --git a/src/lib/components/ui/calendar/calendar-year-select.svelte b/src/lib/components/ui/calendar/calendar-year-select.svelte new file mode 100644 index 0000000..830889a --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-year-select.svelte @@ -0,0 +1,47 @@ + + + + + {#snippet child({ props, selectedYearItem, yearItems })} + + + {/snippet} + + diff --git a/src/lib/components/ui/calendar/calendar.svelte b/src/lib/components/ui/calendar/calendar.svelte new file mode 100644 index 0000000..f9c5154 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar.svelte @@ -0,0 +1,118 @@ + + + + + {#snippet children({ months, weekdays })} + + + + + + {#each months as month, monthIndex (month)} + + + + + + + + {#each weekdays as weekday, i (i)} + + {weekday.slice(0, 2)} + + {/each} + + + + {#each month.weeks as weekDates (weekDates)} + + {#each weekDates as date (date)} + + {#if day} + {@render day({ + day: date, + outsideMonth: !isEqualMonth(date, month.value) + })} + {:else} + + {/if} + + {/each} + + {/each} + + + + {/each} + + {/snippet} + diff --git a/src/lib/components/ui/calendar/index.ts b/src/lib/components/ui/calendar/index.ts new file mode 100644 index 0000000..6cd0f2d --- /dev/null +++ b/src/lib/components/ui/calendar/index.ts @@ -0,0 +1,40 @@ +import Caption from './calendar-caption.svelte'; +import Cell from './calendar-cell.svelte'; +import Day from './calendar-day.svelte'; +import GridBody from './calendar-grid-body.svelte'; +import GridHead from './calendar-grid-head.svelte'; +import GridRow from './calendar-grid-row.svelte'; +import Grid from './calendar-grid.svelte'; +import HeadCell from './calendar-head-cell.svelte'; +import Header from './calendar-header.svelte'; +import Heading from './calendar-heading.svelte'; +import MonthSelect from './calendar-month-select.svelte'; +import Month from './calendar-month.svelte'; +import Months from './calendar-months.svelte'; +import Nav from './calendar-nav.svelte'; +import NextButton from './calendar-next-button.svelte'; +import PrevButton from './calendar-prev-button.svelte'; +import YearSelect from './calendar-year-select.svelte'; +import Root from './calendar.svelte'; + +export { + // + Root as Calendar, + Caption, + Cell, + Day, + Grid, + GridBody, + GridHead, + GridRow, + HeadCell, + Header, + Heading, + Month, + Months, + MonthSelect, + Nav, + NextButton, + PrevButton, + YearSelect +}; diff --git a/src/lib/components/ui/card/card-action.svelte b/src/lib/components/ui/card/card-action.svelte new file mode 100644 index 0000000..e1fdbdf --- /dev/null +++ b/src/lib/components/ui/card/card-action.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/card/card-content.svelte b/src/lib/components/ui/card/card-content.svelte new file mode 100644 index 0000000..b8cdbd3 --- /dev/null +++ b/src/lib/components/ui/card/card-content.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/card/card-description.svelte b/src/lib/components/ui/card/card-description.svelte new file mode 100644 index 0000000..786210e --- /dev/null +++ b/src/lib/components/ui/card/card-description.svelte @@ -0,0 +1,21 @@ + + +

    + {@render children?.()} +

    diff --git a/src/lib/components/ui/card/card-footer.svelte b/src/lib/components/ui/card/card-footer.svelte new file mode 100644 index 0000000..1bd40b2 --- /dev/null +++ b/src/lib/components/ui/card/card-footer.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/card/card-header.svelte b/src/lib/components/ui/card/card-header.svelte new file mode 100644 index 0000000..f2d240c --- /dev/null +++ b/src/lib/components/ui/card/card-header.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/card/card-title.svelte b/src/lib/components/ui/card/card-title.svelte new file mode 100644 index 0000000..abd2433 --- /dev/null +++ b/src/lib/components/ui/card/card-title.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/card/card.svelte b/src/lib/components/ui/card/card.svelte new file mode 100644 index 0000000..8875e33 --- /dev/null +++ b/src/lib/components/ui/card/card.svelte @@ -0,0 +1,26 @@ + + +
    img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col', + className + )} + {...restProps} +> + {@render children?.()} +
    diff --git a/src/lib/components/ui/card/index.ts b/src/lib/components/ui/card/index.ts new file mode 100644 index 0000000..33f0d05 --- /dev/null +++ b/src/lib/components/ui/card/index.ts @@ -0,0 +1,25 @@ +import Action from './card-action.svelte'; +import Content from './card-content.svelte'; +import Description from './card-description.svelte'; +import Footer from './card-footer.svelte'; +import Header from './card-header.svelte'; +import Title from './card-title.svelte'; +import Root from './card.svelte'; + +export { + Action, + // + Root as Card, + Action as CardAction, + Content as CardContent, + Description as CardDescription, + Footer as CardFooter, + Header as CardHeader, + Title as CardTitle, + Content, + Description, + Footer, + Header, + Root, + Title +}; diff --git a/src/lib/components/ui/carousel/carousel-content.svelte b/src/lib/components/ui/carousel/carousel-content.svelte new file mode 100644 index 0000000..65d388d --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-content.svelte @@ -0,0 +1,45 @@ + + +
    +
    + {@render children?.()} +
    +
    diff --git a/src/lib/components/ui/carousel/carousel-item.svelte b/src/lib/components/ui/carousel/carousel-item.svelte new file mode 100644 index 0000000..b457695 --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-item.svelte @@ -0,0 +1,32 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/carousel/carousel-next.svelte b/src/lib/components/ui/carousel/carousel-next.svelte new file mode 100644 index 0000000..ff8b3de --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-next.svelte @@ -0,0 +1,41 @@ + + + diff --git a/src/lib/components/ui/carousel/carousel-previous.svelte b/src/lib/components/ui/carousel/carousel-previous.svelte new file mode 100644 index 0000000..d537f8a --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-previous.svelte @@ -0,0 +1,41 @@ + + + diff --git a/src/lib/components/ui/carousel/carousel.svelte b/src/lib/components/ui/carousel/carousel.svelte new file mode 100644 index 0000000..8eb3045 --- /dev/null +++ b/src/lib/components/ui/carousel/carousel.svelte @@ -0,0 +1,95 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/carousel/context.ts b/src/lib/components/ui/carousel/context.ts new file mode 100644 index 0000000..dabc073 --- /dev/null +++ b/src/lib/components/ui/carousel/context.ts @@ -0,0 +1,59 @@ +import type { WithElementRef } from '$lib/utils.js'; +import type { + default as emblaCarouselSvelte, + EmblaCarouselSvelteType +} from 'embla-carousel-svelte'; +import type { HTMLAttributes } from 'svelte/elements'; + +import { getContext, hasContext, setContext } from 'svelte'; + +export type CarouselAPI = + NonNullable['on:emblaInit']> extends ( + evt: CustomEvent + ) => void + ? CarouselAPI + : never; + +export type CarouselOptions = EmblaCarouselConfig['options']; + +export type CarouselPlugins = EmblaCarouselConfig['plugins']; +export type CarouselProps = { + opts?: CarouselOptions; + orientation?: 'horizontal' | 'vertical'; + plugins?: CarouselPlugins; + setApi?: (api: CarouselAPI | undefined) => void; +} & WithElementRef>; + +//// + +type EmblaCarouselConfig = NonNullable[1]>; + +const EMBLA_CAROUSEL_CONTEXT = Symbol('EMBLA_CAROUSEL_CONTEXT'); + +export type EmblaContext = { + api: CarouselAPI | undefined; + canScrollNext: boolean; + canScrollPrev: boolean; + handleKeyDown: (e: KeyboardEvent) => void; + onInit: (e: CustomEvent) => void; + options: CarouselOptions; + orientation: 'horizontal' | 'vertical'; + plugins: CarouselPlugins; + scrollNext: () => void; + scrollPrev: () => void; + scrollSnaps: number[]; + scrollTo: (index: number, jump?: boolean) => void; + selectedIndex: number; +}; + +export function getEmblaContext(name = 'This component') { + if (!hasContext(EMBLA_CAROUSEL_CONTEXT)) { + throw new Error(`${name} must be used within a component`); + } + return getContext>(EMBLA_CAROUSEL_CONTEXT); +} + +export function setEmblaContext(config: EmblaContext): EmblaContext { + setContext(EMBLA_CAROUSEL_CONTEXT, config); + return config; +} diff --git a/src/lib/components/ui/carousel/index.ts b/src/lib/components/ui/carousel/index.ts new file mode 100644 index 0000000..7215aa2 --- /dev/null +++ b/src/lib/components/ui/carousel/index.ts @@ -0,0 +1,19 @@ +import Content from './carousel-content.svelte'; +import Item from './carousel-item.svelte'; +import Next from './carousel-next.svelte'; +import Previous from './carousel-previous.svelte'; +import Root from './carousel.svelte'; + +export { + // + Root as Carousel, + Content as CarouselContent, + Item as CarouselItem, + Next as CarouselNext, + Previous as CarouselPrevious, + Content, + Item, + Next, + Previous, + Root +}; diff --git a/src/lib/components/ui/chart/chart-container.svelte b/src/lib/components/ui/chart/chart-container.svelte new file mode 100644 index 0000000..e69fa6e --- /dev/null +++ b/src/lib/components/ui/chart/chart-container.svelte @@ -0,0 +1,82 @@ + + +
    + + {@render children?.()} +
    diff --git a/src/lib/components/ui/chart/chart-style.svelte b/src/lib/components/ui/chart/chart-style.svelte new file mode 100644 index 0000000..df183cc --- /dev/null +++ b/src/lib/components/ui/chart/chart-style.svelte @@ -0,0 +1,37 @@ + + +{#if themeContents} + {#key id} + + {themeContents} + + {/key} +{/if} diff --git a/src/lib/components/ui/chart/chart-tooltip.svelte b/src/lib/components/ui/chart/chart-tooltip.svelte new file mode 100644 index 0000000..d6ff326 --- /dev/null +++ b/src/lib/components/ui/chart/chart-tooltip.svelte @@ -0,0 +1,183 @@ + + +{#snippet TooltipLabel()} + {#if formattedLabel} +
    + {#if typeof formattedLabel === 'function'} + {@render formattedLabel()} + {:else} + {formattedLabel} + {/if} +
    + {/if} +{/snippet} + + +
    + {#if !nestLabel} + {@render TooltipLabel()} + {/if} +
    + {#each visibleSeries as item, i (item.key + i)} + {@const key = `${nameKey || item.key || item.label || 'value'}`} + {@const itemConfig = getPayloadConfigFromPayload( + chart.config, + item, + key, + chartCtx.tooltip.data + )} + {@const indicatorColor = color || item.config?.color || item.color} +
    svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:size-2.5', + indicator === 'dot' && 'items-center' + )} + > + {#if formatter && item.value !== undefined && item.label} + {@render formatter({ + index: i, + item, + name: item.label, + payload: visibleSeries, + value: item.value + })} + {:else} + {#if itemConfig?.icon} + + {:else if !hideIndicator} +
    + {/if} +
    +
    + {#if nestLabel} + {@render TooltipLabel()} + {/if} + + {itemConfig?.label || item.label} + +
    + {#if item.value !== undefined} + + {item.value.toLocaleString()} + + {/if} +
    + {/if} +
    + {/each} +
    +
    +
    diff --git a/src/lib/components/ui/chart/chart-utils.ts b/src/lib/components/ui/chart/chart-utils.ts new file mode 100644 index 0000000..1baa8db --- /dev/null +++ b/src/lib/components/ui/chart/chart-utils.ts @@ -0,0 +1,69 @@ +import type { Tooltip } from 'layerchart'; + +import { type Component, getContext, setContext, type Snippet } from 'svelte'; + +export const THEMES = { dark: '.dark', light: '' } as const; + +export type ChartConfig = { + [k in string]: ( + | { color?: never; theme: Record } + | { color?: string; theme?: never } + ) & { + icon?: Component; + label?: string; + }; +}; + +export type ExtractSnippetParams = T extends Snippet<[infer P]> ? P : never; + +export type TooltipPayload = Tooltip.TooltipSeries; + +type ChartContextValue = { + config: ChartConfig; +}; + +// Helper to extract item config from a payload. +export function getPayloadConfigFromPayload( + config: ChartConfig, + payload: TooltipPayload, + key: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data?: null | Record +) { + if (typeof payload !== 'object' || payload === null) return undefined; + + const payloadConfig = + 'config' in payload && typeof payload.config === 'object' && payload.config !== null + ? payload.config + : undefined; + + let configLabelKey: string = key; + + if (payload.key === key) { + configLabelKey = payload.key; + } else if (payload.label === key) { + configLabelKey = payload.label; + } else if (key in payload && typeof payload[key as keyof typeof payload] === 'string') { + configLabelKey = payload[key as keyof typeof payload] as string; + } else if ( + payloadConfig !== undefined && + key in payloadConfig && + typeof payloadConfig[key as keyof typeof payloadConfig] === 'string' + ) { + configLabelKey = payloadConfig[key as keyof typeof payloadConfig] as string; + } else if (data != null && key in data && typeof data[key] === 'string') { + configLabelKey = data[key] as string; + } + + return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]; +} + +const chartContextKey = Symbol('chart-context'); + +export function setChartContext(value: ChartContextValue) { + return setContext(chartContextKey, value); +} + +export function useChart() { + return getContext(chartContextKey); +} diff --git a/src/lib/components/ui/chart/index.ts b/src/lib/components/ui/chart/index.ts new file mode 100644 index 0000000..b59c0c5 --- /dev/null +++ b/src/lib/components/ui/chart/index.ts @@ -0,0 +1,6 @@ +import ChartContainer from './chart-container.svelte'; +import ChartTooltip from './chart-tooltip.svelte'; + +export { type ChartConfig, getPayloadConfigFromPayload } from './chart-utils.js'; + +export { ChartContainer, ChartTooltip, ChartContainer as Container, ChartTooltip as Tooltip }; diff --git a/src/lib/components/ui/checkbox/checkbox.svelte b/src/lib/components/ui/checkbox/checkbox.svelte new file mode 100644 index 0000000..f008486 --- /dev/null +++ b/src/lib/components/ui/checkbox/checkbox.svelte @@ -0,0 +1,39 @@ + + + + {#snippet children({ checked, indeterminate })} +
    + {#if checked} + + {:else if indeterminate} + + {/if} +
    + {/snippet} +
    diff --git a/src/lib/components/ui/checkbox/index.ts b/src/lib/components/ui/checkbox/index.ts new file mode 100644 index 0000000..ae97cfc --- /dev/null +++ b/src/lib/components/ui/checkbox/index.ts @@ -0,0 +1,6 @@ +import Root from './checkbox.svelte'; +export { + // + Root as Checkbox, + Root +}; diff --git a/src/lib/components/ui/collapsible/collapsible-content.svelte b/src/lib/components/ui/collapsible/collapsible-content.svelte new file mode 100644 index 0000000..59b068c --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible-content.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/collapsible/collapsible-trigger.svelte b/src/lib/components/ui/collapsible/collapsible-trigger.svelte new file mode 100644 index 0000000..c88ceba --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/collapsible/collapsible.svelte b/src/lib/components/ui/collapsible/collapsible.svelte new file mode 100644 index 0000000..68f56df --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/collapsible/index.ts b/src/lib/components/ui/collapsible/index.ts new file mode 100644 index 0000000..768e9de --- /dev/null +++ b/src/lib/components/ui/collapsible/index.ts @@ -0,0 +1,13 @@ +import Content from './collapsible-content.svelte'; +import Trigger from './collapsible-trigger.svelte'; +import Root from './collapsible.svelte'; + +export { + // + Root as Collapsible, + Content as CollapsibleContent, + Trigger as CollapsibleTrigger, + Content, + Root, + Trigger +}; diff --git a/src/lib/components/ui/command/command-dialog.svelte b/src/lib/components/ui/command/command-dialog.svelte new file mode 100644 index 0000000..92371e7 --- /dev/null +++ b/src/lib/components/ui/command/command-dialog.svelte @@ -0,0 +1,44 @@ + + + + + {title} + {description} + + + + + diff --git a/src/lib/components/ui/command/command-empty.svelte b/src/lib/components/ui/command/command-empty.svelte new file mode 100644 index 0000000..570e6ca --- /dev/null +++ b/src/lib/components/ui/command/command-empty.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/command/command-group.svelte b/src/lib/components/ui/command/command-group.svelte new file mode 100644 index 0000000..3557235 --- /dev/null +++ b/src/lib/components/ui/command/command-group.svelte @@ -0,0 +1,33 @@ + + + + {#if heading} + + {heading} + + {/if} + + diff --git a/src/lib/components/ui/command/command-input.svelte b/src/lib/components/ui/command/command-input.svelte new file mode 100644 index 0000000..fd37718 --- /dev/null +++ b/src/lib/components/ui/command/command-input.svelte @@ -0,0 +1,36 @@ + + +
    + + + {#snippet child({ props })} + + {/snippet} + + + + + +
    diff --git a/src/lib/components/ui/command/command-item.svelte b/src/lib/components/ui/command/command-item.svelte new file mode 100644 index 0000000..f781b5c --- /dev/null +++ b/src/lib/components/ui/command/command-item.svelte @@ -0,0 +1,27 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/command/command-link-item.svelte b/src/lib/components/ui/command/command-link-item.svelte new file mode 100644 index 0000000..4271620 --- /dev/null +++ b/src/lib/components/ui/command/command-link-item.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/command/command-list.svelte b/src/lib/components/ui/command/command-list.svelte new file mode 100644 index 0000000..78dfe3e --- /dev/null +++ b/src/lib/components/ui/command/command-list.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/command/command-loading.svelte b/src/lib/components/ui/command/command-loading.svelte new file mode 100644 index 0000000..0aaf5c3 --- /dev/null +++ b/src/lib/components/ui/command/command-loading.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/command/command-separator.svelte b/src/lib/components/ui/command/command-separator.svelte new file mode 100644 index 0000000..a4d80e9 --- /dev/null +++ b/src/lib/components/ui/command/command-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/command/command-shortcut.svelte b/src/lib/components/ui/command/command-shortcut.svelte new file mode 100644 index 0000000..cad8479 --- /dev/null +++ b/src/lib/components/ui/command/command-shortcut.svelte @@ -0,0 +1,24 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/command/command.svelte b/src/lib/components/ui/command/command.svelte new file mode 100644 index 0000000..8f9a31e --- /dev/null +++ b/src/lib/components/ui/command/command.svelte @@ -0,0 +1,28 @@ + + + diff --git a/src/lib/components/ui/command/index.ts b/src/lib/components/ui/command/index.ts new file mode 100644 index 0000000..d2f1129 --- /dev/null +++ b/src/lib/components/ui/command/index.ts @@ -0,0 +1,37 @@ +import Dialog from './command-dialog.svelte'; +import Empty from './command-empty.svelte'; +import Group from './command-group.svelte'; +import Input from './command-input.svelte'; +import Item from './command-item.svelte'; +import LinkItem from './command-link-item.svelte'; +import List from './command-list.svelte'; +import Loading from './command-loading.svelte'; +import Separator from './command-separator.svelte'; +import Shortcut from './command-shortcut.svelte'; +import Root from './command.svelte'; + +export { + // + Root as Command, + Dialog as CommandDialog, + Empty as CommandEmpty, + Group as CommandGroup, + Input as CommandInput, + Item as CommandItem, + LinkItem as CommandLinkItem, + List as CommandList, + Loading as CommandLoading, + Separator as CommandSeparator, + Shortcut as CommandShortcut, + Dialog, + Empty, + Group, + Input, + Item, + LinkItem, + List, + Loading, + Root, + Separator, + Shortcut +}; diff --git a/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte b/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte new file mode 100644 index 0000000..930eb4e --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte @@ -0,0 +1,42 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/src/lib/components/ui/context-menu/context-menu-content.svelte b/src/lib/components/ui/context-menu/context-menu-content.svelte new file mode 100644 index 0000000..16e3525 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-content.svelte @@ -0,0 +1,30 @@ + + + + + diff --git a/src/lib/components/ui/context-menu/context-menu-group-heading.svelte b/src/lib/components/ui/context-menu/context-menu-group-heading.svelte new file mode 100644 index 0000000..25ed9c1 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-group-heading.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-group.svelte b/src/lib/components/ui/context-menu/context-menu-group.svelte new file mode 100644 index 0000000..0a5a142 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-item.svelte b/src/lib/components/ui/context-menu/context-menu-item.svelte new file mode 100644 index 0000000..25d20b5 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-label.svelte b/src/lib/components/ui/context-menu/context-menu-label.svelte new file mode 100644 index 0000000..78d2481 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-label.svelte @@ -0,0 +1,28 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/context-menu/context-menu-portal.svelte b/src/lib/components/ui/context-menu/context-menu-portal.svelte new file mode 100644 index 0000000..d03821a --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-radio-group.svelte b/src/lib/components/ui/context-menu/context-menu-radio-group.svelte new file mode 100644 index 0000000..bd63b9f --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-radio-item.svelte b/src/lib/components/ui/context-menu/context-menu-radio-item.svelte new file mode 100644 index 0000000..b56dc8d --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/src/lib/components/ui/context-menu/context-menu-separator.svelte b/src/lib/components/ui/context-menu/context-menu-separator.svelte new file mode 100644 index 0000000..de707cc --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-shortcut.svelte b/src/lib/components/ui/context-menu/context-menu-shortcut.svelte new file mode 100644 index 0000000..7ee571d --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-shortcut.svelte @@ -0,0 +1,24 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/context-menu/context-menu-sub-content.svelte b/src/lib/components/ui/context-menu/context-menu-sub-content.svelte new file mode 100644 index 0000000..12ef6ac --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte b/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte new file mode 100644 index 0000000..81b8fa0 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/context-menu/context-menu-sub.svelte b/src/lib/components/ui/context-menu/context-menu-sub.svelte new file mode 100644 index 0000000..c47f6f3 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-trigger.svelte b/src/lib/components/ui/context-menu/context-menu-trigger.svelte new file mode 100644 index 0000000..a15de20 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-trigger.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu.svelte b/src/lib/components/ui/context-menu/context-menu.svelte new file mode 100644 index 0000000..486e3ad --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/index.ts b/src/lib/components/ui/context-menu/index.ts new file mode 100644 index 0000000..7511161 --- /dev/null +++ b/src/lib/components/ui/context-menu/index.ts @@ -0,0 +1,52 @@ +import CheckboxItem from './context-menu-checkbox-item.svelte'; +import Content from './context-menu-content.svelte'; +import GroupHeading from './context-menu-group-heading.svelte'; +import Group from './context-menu-group.svelte'; +import Item from './context-menu-item.svelte'; +import Label from './context-menu-label.svelte'; +import Portal from './context-menu-portal.svelte'; +import RadioGroup from './context-menu-radio-group.svelte'; +import RadioItem from './context-menu-radio-item.svelte'; +import Separator from './context-menu-separator.svelte'; +import Shortcut from './context-menu-shortcut.svelte'; +import SubContent from './context-menu-sub-content.svelte'; +import SubTrigger from './context-menu-sub-trigger.svelte'; +import Sub from './context-menu-sub.svelte'; +import Trigger from './context-menu-trigger.svelte'; +import Root from './context-menu.svelte'; + +export { + CheckboxItem, + Content, + // + Root as ContextMenu, + CheckboxItem as ContextMenuCheckboxItem, + Content as ContextMenuContent, + Group as ContextMenuGroup, + GroupHeading as ContextMenuGroupHeading, + Item as ContextMenuItem, + Label as ContextMenuLabel, + Portal as ContextMenuPortal, + RadioGroup as ContextMenuRadioGroup, + RadioItem as ContextMenuRadioItem, + Separator as ContextMenuSeparator, + Shortcut as ContextMenuShortcut, + Sub as ContextMenuSub, + SubContent as ContextMenuSubContent, + SubTrigger as ContextMenuSubTrigger, + Trigger as ContextMenuTrigger, + Group, + GroupHeading, + Item, + Label, + Portal, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger +}; diff --git a/src/lib/components/ui/data-table/data-table.svelte.ts b/src/lib/components/ui/data-table/data-table.svelte.ts new file mode 100644 index 0000000..4025a14 --- /dev/null +++ b/src/lib/components/ui/data-table/data-table.svelte.ts @@ -0,0 +1,142 @@ +import { + createTable, + type RowData, + type TableOptions, + type TableOptionsResolved, + type TableState, + type Updater +} from '@tanstack/table-core'; + +type Intersection = {} & (T extends [infer H, ...infer R] + ? H & Intersection + : unknown); + +type MaybeThunk = (() => null | T | undefined) | T; +/** + * Creates a reactive TanStack table object for Svelte. + * @param options Table options to create the table with. + * @returns A reactive table object. + * @example + * ```svelte + * + * + * + * + * {#each table.getHeaderGroups() as headerGroup} + * + * {#each headerGroup.headers as header} + * + * {/each} + * + * {/each} + * + * + *
    + * + *
    + * ``` + */ +export function createSvelteTable(options: TableOptions) { + const resolvedOptions: TableOptionsResolved = mergeObjects( + { + mergeOptions: ( + defaultOptions: TableOptions, + options: Partial> + ) => { + return mergeObjects(defaultOptions, options); + }, + onStateChange() {}, + renderFallbackValue: null, + state: {} + }, + options + ); + + const table = createTable(resolvedOptions); + let state = $state(table.initialState); + + function updateOptions() { + table.setOptions(() => { + return mergeObjects(resolvedOptions, options, { + onStateChange: (updater: Updater) => { + if (updater instanceof Function) state = updater(state); + else state = mergeObjects(state, updater); + + options.onStateChange?.(updater); + }, + + state: mergeObjects(state, options.state || {}) + }); + }); + } + + updateOptions(); + + $effect.pre(() => { + updateOptions(); + }); + + return table; +} + +/** + * Lazily merges several objects (or thunks) while preserving + * getter semantics from every source. + * + * Proxy-based to avoid known WebKit recursion issue. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function mergeObjects[]>( + ...sources: Sources +): Intersection<{ [K in keyof Sources]: Sources[K] }> { + const resolve = (src: MaybeThunk): T | undefined => + typeof src === 'function' ? (src() ?? undefined) : src; + + const findSourceWithKey = (key: PropertyKey) => { + for (let i = sources.length - 1; i >= 0; i--) { + const obj = resolve(sources[i]); + if (obj && key in obj) return obj; + } + return undefined; + }; + + return new Proxy(Object.create(null), { + get(_, key) { + const src = findSourceWithKey(key); + + return src?.[key as never]; + }, + + getOwnPropertyDescriptor(_, key) { + const src = findSourceWithKey(key); + if (!src) return undefined; + return { + configurable: true, + enumerable: true, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: (src as any)[key], + writable: true + }; + }, + + has(_, key) { + return !!findSourceWithKey(key); + }, + + ownKeys(): (string | symbol)[] { + // eslint-disable-next-line svelte/prefer-svelte-reactivity + const all = new Set(); + for (const s of sources) { + const obj = resolve(s); + if (obj) { + for (const k of Reflect.ownKeys(obj) as (string | symbol)[]) { + all.add(k); + } + } + } + return [...all]; + } + }) as Intersection<{ [K in keyof Sources]: Sources[K] }>; +} diff --git a/src/lib/components/ui/data-table/flex-render.svelte b/src/lib/components/ui/data-table/flex-render.svelte new file mode 100644 index 0000000..89845bb --- /dev/null +++ b/src/lib/components/ui/data-table/flex-render.svelte @@ -0,0 +1,41 @@ + + +{#if typeof content === 'string'} + {content} +{:else if content instanceof Function} + + + {@const result = content(context as any)} + {#if result instanceof RenderComponentConfig} + {@const { component: Component, props } = result} + + {:else if result instanceof RenderSnippetConfig} + {@const { params, snippet } = result} + {@render snippet({ ...params, attach })} + {:else} + {result} + {/if} +{/if} diff --git a/src/lib/components/ui/data-table/index.ts b/src/lib/components/ui/data-table/index.ts new file mode 100644 index 0000000..56ae024 --- /dev/null +++ b/src/lib/components/ui/data-table/index.ts @@ -0,0 +1,3 @@ +export { createSvelteTable } from './data-table.svelte.js'; +export { default as FlexRender } from './flex-render.svelte'; +export { renderComponent, renderSnippet } from './render-helpers.js'; diff --git a/src/lib/components/ui/data-table/render-helpers.ts b/src/lib/components/ui/data-table/render-helpers.ts new file mode 100644 index 0000000..5c945a7 --- /dev/null +++ b/src/lib/components/ui/data-table/render-helpers.ts @@ -0,0 +1,111 @@ +import type { Component, ComponentProps, Snippet } from 'svelte'; + +/** + * A helper class to make it easy to identify Svelte components in + * `columnDef.cell` and `columnDef.header` properties. + * + * > NOTE: This class should only be used internally by the adapter. If you're + * reading this and you don't know what this is for, you probably don't need it. + * + * @example + * ```svelte + * {@const result = content(context as any)} + * {#if result instanceof RenderComponentConfig} + * {@const { component: Component, props } = result} + * + * {/if} + * ``` + */ +export class RenderComponentConfig { + component: TComponent; + props: ComponentProps | Record; + constructor( + component: TComponent, + props: ComponentProps | Record = {} + ) { + this.component = component; + this.props = props; + } +} + +/** + * A helper class to make it easy to identify Svelte Snippets in `columnDef.cell` and `columnDef.header` properties. + * + * > NOTE: This class should only be used internally by the adapter. If you're + * reading this and you don't know what this is for, you probably don't need it. + * + * @example + * ```svelte + * {@const result = content(context as any)} + * {#if result instanceof RenderSnippetConfig} + * {@const { snippet, params } = result} + * {@render snippet(params)} + * {/if} + * ``` + */ +export class RenderSnippetConfig { + params: TProps; + snippet: Snippet<[TProps]>; + constructor(snippet: Snippet<[TProps]>, params: TProps) { + this.snippet = snippet; + this.params = params; + } +} + +/** + * A helper function to help create cells from Svelte components through ColumnDef's `cell` and `header` properties. + * + * This is only to be used with Svelte Components - use `renderSnippet` for Svelte Snippets. + * + * @param component A Svelte component + * @param props The props to pass to `component` + * @returns A `RenderComponentConfig` object that helps svelte-table know how to render the header/cell component. + * @example + * ```ts + * // +page.svelte + * const defaultColumns = [ + * columnHelper.accessor('name', { + * header: header => renderComponent(SortHeader, { label: 'Name', header }), + * }), + * columnHelper.accessor('state', { + * header: header => renderComponent(SortHeader, { label: 'State', header }), + * }), + * ] + * ``` + * @see {@link https://tanstack.com/table/latest/docs/guide/column-defs} + */ +export function renderComponent< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + T extends Component, + Props extends ComponentProps +>(component: T, props: Props = {} as Props) { + return new RenderComponentConfig(component, props); +} + +/** + * A helper function to help create cells from Svelte Snippets through ColumnDef's `cell` and `header` properties. + * + * The snippet must only take one parameter. + * + * This is only to be used with Snippets - use `renderComponent` for Svelte Components. + * + * @param snippet + * @param params + * @returns - A `RenderSnippetConfig` object that helps svelte-table know how to render the header/cell snippet. + * @example + * ```ts + * // +page.svelte + * const defaultColumns = [ + * columnHelper.accessor('name', { + * cell: cell => renderSnippet(nameSnippet, { name: cell.row.name }), + * }), + * columnHelper.accessor('state', { + * cell: cell => renderSnippet(stateSnippet, { state: cell.row.state }), + * }), + * ] + * ``` + * @see {@link https://tanstack.com/table/latest/docs/guide/column-defs} + */ +export function renderSnippet(snippet: Snippet<[TProps]>, params: TProps = {} as TProps) { + return new RenderSnippetConfig(snippet, params); +} diff --git a/src/lib/components/ui/dialog/dialog-close.svelte b/src/lib/components/ui/dialog/dialog-close.svelte new file mode 100644 index 0000000..4141704 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-close.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-content.svelte b/src/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 0000000..fbd78ae --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,50 @@ + + + + + + {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} + + diff --git a/src/lib/components/ui/dialog/dialog-description.svelte b/src/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 0000000..e933406 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-footer.svelte b/src/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 0000000..164bf48 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,36 @@ + + +
    + {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} +
    diff --git a/src/lib/components/ui/dialog/dialog-header.svelte b/src/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 0000000..0429ccb --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/dialog/dialog-overlay.svelte b/src/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 0000000..b6352da --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-portal.svelte b/src/lib/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 0000000..a60a85e --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-title.svelte b/src/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 0000000..4ba85f4 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog-trigger.svelte b/src/lib/components/ui/dialog/dialog-trigger.svelte new file mode 100644 index 0000000..9264541 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/dialog/dialog.svelte b/src/lib/components/ui/dialog/dialog.svelte new file mode 100644 index 0000000..c1444b2 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dialog/index.ts b/src/lib/components/ui/dialog/index.ts new file mode 100644 index 0000000..705073d --- /dev/null +++ b/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,34 @@ +import Close from './dialog-close.svelte'; +import Content from './dialog-content.svelte'; +import Description from './dialog-description.svelte'; +import Footer from './dialog-footer.svelte'; +import Header from './dialog-header.svelte'; +import Overlay from './dialog-overlay.svelte'; +import Portal from './dialog-portal.svelte'; +import Title from './dialog-title.svelte'; +import Trigger from './dialog-trigger.svelte'; +import Root from './dialog.svelte'; + +export { + Close, + Content, + Description, + // + Root as Dialog, + Close as DialogClose, + Content as DialogContent, + Description as DialogDescription, + Footer as DialogFooter, + Header as DialogHeader, + Overlay as DialogOverlay, + Portal as DialogPortal, + Title as DialogTitle, + Trigger as DialogTrigger, + Footer, + Header, + Overlay, + Portal, + Root, + Title, + Trigger +}; diff --git a/src/lib/components/ui/drawer/drawer-close.svelte b/src/lib/components/ui/drawer/drawer-close.svelte new file mode 100644 index 0000000..aea8d1e --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-content.svelte b/src/lib/components/ui/drawer/drawer-content.svelte new file mode 100644 index 0000000..97b0db7 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-content.svelte @@ -0,0 +1,38 @@ + + + + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/drawer/drawer-description.svelte b/src/lib/components/ui/drawer/drawer-description.svelte new file mode 100644 index 0000000..92e4214 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-footer.svelte b/src/lib/components/ui/drawer/drawer-footer.svelte new file mode 100644 index 0000000..6ad8b39 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-footer.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/drawer/drawer-header.svelte b/src/lib/components/ui/drawer/drawer-header.svelte new file mode 100644 index 0000000..4f06282 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-header.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/drawer/drawer-nested.svelte b/src/lib/components/ui/drawer/drawer-nested.svelte new file mode 100644 index 0000000..f9c4193 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-nested.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-overlay.svelte b/src/lib/components/ui/drawer/drawer-overlay.svelte new file mode 100644 index 0000000..96d4890 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-portal.svelte b/src/lib/components/ui/drawer/drawer-portal.svelte new file mode 100644 index 0000000..5a2b942 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-title.svelte b/src/lib/components/ui/drawer/drawer-title.svelte new file mode 100644 index 0000000..f94d271 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer-trigger.svelte b/src/lib/components/ui/drawer/drawer-trigger.svelte new file mode 100644 index 0000000..672d356 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/drawer/drawer.svelte b/src/lib/components/ui/drawer/drawer.svelte new file mode 100644 index 0000000..e049f13 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/drawer/index.ts b/src/lib/components/ui/drawer/index.ts new file mode 100644 index 0000000..30a7d77 --- /dev/null +++ b/src/lib/components/ui/drawer/index.ts @@ -0,0 +1,37 @@ +import Close from './drawer-close.svelte'; +import Content from './drawer-content.svelte'; +import Description from './drawer-description.svelte'; +import Footer from './drawer-footer.svelte'; +import Header from './drawer-header.svelte'; +import NestedRoot from './drawer-nested.svelte'; +import Overlay from './drawer-overlay.svelte'; +import Portal from './drawer-portal.svelte'; +import Title from './drawer-title.svelte'; +import Trigger from './drawer-trigger.svelte'; +import Root from './drawer.svelte'; + +export { + Close, + Content, + Description, + // + Root as Drawer, + Close as DrawerClose, + Content as DrawerContent, + Description as DrawerDescription, + Footer as DrawerFooter, + Header as DrawerHeader, + NestedRoot as DrawerNestedRoot, + Overlay as DrawerOverlay, + Portal as DrawerPortal, + Title as DrawerTitle, + Trigger as DrawerTrigger, + Footer, + Header, + NestedRoot, + Overlay, + Portal, + Root, + Title, + Trigger +}; diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte new file mode 100644 index 0000000..c0bf94b --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 0000000..840a694 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,45 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 0000000..a0777e8 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,33 @@ + + + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte new file mode 100644 index 0000000..f88d24a --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte new file mode 100644 index 0000000..261ab7e --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 0000000..1d93587 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 0000000..24e0312 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,28 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte new file mode 100644 index 0000000..089a25c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 0000000..3e98749 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 0000000..9002c6d --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,34 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 0000000..5255b81 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 0000000..b64c5a7 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,24 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 0000000..e1945b2 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 0000000..a86fde0 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte new file mode 100644 index 0000000..9cfa3b8 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte new file mode 100644 index 0000000..032b645 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte new file mode 100644 index 0000000..fbbb790 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/index.ts b/src/lib/components/ui/dropdown-menu/index.ts new file mode 100644 index 0000000..107e6ba --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,54 @@ +import CheckboxGroup from './dropdown-menu-checkbox-group.svelte'; +import CheckboxItem from './dropdown-menu-checkbox-item.svelte'; +import Content from './dropdown-menu-content.svelte'; +import GroupHeading from './dropdown-menu-group-heading.svelte'; +import Group from './dropdown-menu-group.svelte'; +import Item from './dropdown-menu-item.svelte'; +import Label from './dropdown-menu-label.svelte'; +import Portal from './dropdown-menu-portal.svelte'; +import RadioGroup from './dropdown-menu-radio-group.svelte'; +import RadioItem from './dropdown-menu-radio-item.svelte'; +import Separator from './dropdown-menu-separator.svelte'; +import Shortcut from './dropdown-menu-shortcut.svelte'; +import SubContent from './dropdown-menu-sub-content.svelte'; +import SubTrigger from './dropdown-menu-sub-trigger.svelte'; +import Sub from './dropdown-menu-sub.svelte'; +import Trigger from './dropdown-menu-trigger.svelte'; +import Root from './dropdown-menu.svelte'; + +export { + CheckboxGroup, + CheckboxItem, + Content, + Root as DropdownMenu, + CheckboxGroup as DropdownMenuCheckboxGroup, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Group as DropdownMenuGroup, + GroupHeading as DropdownMenuGroupHeading, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + Portal as DropdownMenuPortal, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + Group, + GroupHeading, + Item, + Label, + Portal, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger +}; diff --git a/src/lib/components/ui/empty/empty-content.svelte b/src/lib/components/ui/empty/empty-content.svelte new file mode 100644 index 0000000..8c5b5b4 --- /dev/null +++ b/src/lib/components/ui/empty/empty-content.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/empty/empty-description.svelte b/src/lib/components/ui/empty/empty-description.svelte new file mode 100644 index 0000000..834bcea --- /dev/null +++ b/src/lib/components/ui/empty/empty-description.svelte @@ -0,0 +1,24 @@ + + +
    a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4', + className + )} + {...restProps} +> + {@render children?.()} +
    diff --git a/src/lib/components/ui/empty/empty-header.svelte b/src/lib/components/ui/empty/empty-header.svelte new file mode 100644 index 0000000..1aa0762 --- /dev/null +++ b/src/lib/components/ui/empty/empty-header.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/empty/empty-media.svelte b/src/lib/components/ui/empty/empty-media.svelte new file mode 100644 index 0000000..b32ab82 --- /dev/null +++ b/src/lib/components/ui/empty/empty-media.svelte @@ -0,0 +1,42 @@ + + + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/empty/empty-title.svelte b/src/lib/components/ui/empty/empty-title.svelte new file mode 100644 index 0000000..29f1142 --- /dev/null +++ b/src/lib/components/ui/empty/empty-title.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/empty/empty.svelte b/src/lib/components/ui/empty/empty.svelte new file mode 100644 index 0000000..85f225d --- /dev/null +++ b/src/lib/components/ui/empty/empty.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/empty/index.ts b/src/lib/components/ui/empty/index.ts new file mode 100644 index 0000000..d1a95e0 --- /dev/null +++ b/src/lib/components/ui/empty/index.ts @@ -0,0 +1,22 @@ +import Content from './empty-content.svelte'; +import Description from './empty-description.svelte'; +import Header from './empty-header.svelte'; +import Media from './empty-media.svelte'; +import Title from './empty-title.svelte'; +import Root from './empty.svelte'; + +export { + Content, + Description, + // + Root as Empty, + Content as EmptyContent, + Description as EmptyDescription, + Header as EmptyHeader, + Media as EmptyMedia, + Title as EmptyTitle, + Header, + Media, + Root, + Title +}; diff --git a/src/lib/components/ui/field/field-content.svelte b/src/lib/components/ui/field/field-content.svelte new file mode 100644 index 0000000..3ca7df8 --- /dev/null +++ b/src/lib/components/ui/field/field-content.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/field/field-description.svelte b/src/lib/components/ui/field/field-description.svelte new file mode 100644 index 0000000..6435573 --- /dev/null +++ b/src/lib/components/ui/field/field-description.svelte @@ -0,0 +1,26 @@ + + +

    a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4', + className + )} + {...restProps} +> + {@render children?.()} +

    diff --git a/src/lib/components/ui/field/field-error.svelte b/src/lib/components/ui/field/field-error.svelte new file mode 100644 index 0000000..38ce685 --- /dev/null +++ b/src/lib/components/ui/field/field-error.svelte @@ -0,0 +1,59 @@ + + +{#if hasContent} + +{/if} diff --git a/src/lib/components/ui/field/field-group.svelte b/src/lib/components/ui/field/field-group.svelte new file mode 100644 index 0000000..747025d --- /dev/null +++ b/src/lib/components/ui/field/field-group.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/field/field-label.svelte b/src/lib/components/ui/field/field-label.svelte new file mode 100644 index 0000000..f5f8e8b --- /dev/null +++ b/src/lib/components/ui/field/field-label.svelte @@ -0,0 +1,26 @@ + + + diff --git a/src/lib/components/ui/field/field-legend.svelte b/src/lib/components/ui/field/field-legend.svelte new file mode 100644 index 0000000..26d4566 --- /dev/null +++ b/src/lib/components/ui/field/field-legend.svelte @@ -0,0 +1,28 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/field/field-separator.svelte b/src/lib/components/ui/field/field-separator.svelte new file mode 100644 index 0000000..3586fc7 --- /dev/null +++ b/src/lib/components/ui/field/field-separator.svelte @@ -0,0 +1,36 @@ + + +
    + + {#if children} + + {@render children()} + + {/if} +
    diff --git a/src/lib/components/ui/field/field-set.svelte b/src/lib/components/ui/field/field-set.svelte new file mode 100644 index 0000000..aa37377 --- /dev/null +++ b/src/lib/components/ui/field/field-set.svelte @@ -0,0 +1,24 @@ + + +
    [data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col', + className + )} + {...restProps} +> + {@render children?.()} +
    diff --git a/src/lib/components/ui/field/field-title.svelte b/src/lib/components/ui/field/field-title.svelte new file mode 100644 index 0000000..c8ad6e4 --- /dev/null +++ b/src/lib/components/ui/field/field-title.svelte @@ -0,0 +1,24 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/field/field.svelte b/src/lib/components/ui/field/field.svelte new file mode 100644 index 0000000..80f4c62 --- /dev/null +++ b/src/lib/components/ui/field/field.svelte @@ -0,0 +1,48 @@ + + + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/field/index.ts b/src/lib/components/ui/field/index.ts new file mode 100644 index 0000000..d37bccb --- /dev/null +++ b/src/lib/components/ui/field/index.ts @@ -0,0 +1,33 @@ +import Content from './field-content.svelte'; +import Description from './field-description.svelte'; +import Error from './field-error.svelte'; +import Group from './field-group.svelte'; +import Label from './field-label.svelte'; +import Legend from './field-legend.svelte'; +import Separator from './field-separator.svelte'; +import Set from './field-set.svelte'; +import Title from './field-title.svelte'; +import Field from './field.svelte'; + +export { + Content, + Description, + Error, + Field, + Content as FieldContent, + Description as FieldDescription, + Error as FieldError, + Group as FieldGroup, + Label as FieldLabel, + Legend as FieldLegend, + Separator as FieldSeparator, + // + Set as FieldSet, + Title as FieldTitle, + Group, + Label, + Legend, + Separator, + Set, + Title +}; diff --git a/src/lib/components/ui/form/form-button.svelte b/src/lib/components/ui/form/form-button.svelte new file mode 100644 index 0000000..0b31006 --- /dev/null +++ b/src/lib/components/ui/form/form-button.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/input-group/input-group-input.svelte b/src/lib/components/ui/input-group/input-group-input.svelte new file mode 100644 index 0000000..70bae24 --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-input.svelte @@ -0,0 +1,24 @@ + + + diff --git a/src/lib/components/ui/input-group/input-group-text.svelte b/src/lib/components/ui/input-group/input-group-text.svelte new file mode 100644 index 0000000..5e0fc3f --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-text.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/input-group/input-group-textarea.svelte b/src/lib/components/ui/input-group/input-group-textarea.svelte new file mode 100644 index 0000000..b36659a --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-textarea.svelte @@ -0,0 +1,24 @@ + + + diff --git a/src/lib/components/ui/toggle-group/index.ts b/src/lib/components/ui/toggle-group/index.ts new file mode 100644 index 0000000..88ec8ea --- /dev/null +++ b/src/lib/components/ui/toggle-group/index.ts @@ -0,0 +1,10 @@ +import Item from './toggle-group-item.svelte'; +import Root from './toggle-group.svelte'; + +export { + Item, + Root, + // + Root as ToggleGroup, + Item as ToggleGroupItem +}; diff --git a/src/lib/components/ui/toggle-group/toggle-group-item.svelte b/src/lib/components/ui/toggle-group/toggle-group-item.svelte new file mode 100644 index 0000000..e875acf --- /dev/null +++ b/src/lib/components/ui/toggle-group/toggle-group-item.svelte @@ -0,0 +1,36 @@ + + + diff --git a/src/lib/components/ui/toggle-group/toggle-group.svelte b/src/lib/components/ui/toggle-group/toggle-group.svelte new file mode 100644 index 0000000..742dc75 --- /dev/null +++ b/src/lib/components/ui/toggle-group/toggle-group.svelte @@ -0,0 +1,76 @@ + + + + + + diff --git a/src/lib/components/ui/toggle/index.ts b/src/lib/components/ui/toggle/index.ts new file mode 100644 index 0000000..85e8504 --- /dev/null +++ b/src/lib/components/ui/toggle/index.ts @@ -0,0 +1,13 @@ +import Root from './toggle.svelte'; +export { + type ToggleSize, + type ToggleVariant, + toggleVariants, + type ToggleVariants +} from './toggle.svelte'; + +export { + Root, + // + Root as Toggle +}; diff --git a/src/lib/components/ui/toggle/toggle.svelte b/src/lib/components/ui/toggle/toggle.svelte new file mode 100644 index 0000000..13f7803 --- /dev/null +++ b/src/lib/components/ui/toggle/toggle.svelte @@ -0,0 +1,52 @@ + + + + + diff --git a/src/lib/components/ui/tooltip/index.ts b/src/lib/components/ui/tooltip/index.ts new file mode 100644 index 0000000..7e8d917 --- /dev/null +++ b/src/lib/components/ui/tooltip/index.ts @@ -0,0 +1,19 @@ +import Content from './tooltip-content.svelte'; +import Portal from './tooltip-portal.svelte'; +import Provider from './tooltip-provider.svelte'; +import Trigger from './tooltip-trigger.svelte'; +import Root from './tooltip.svelte'; + +export { + Content, + Portal, + Provider, + Root, + // + Root as Tooltip, + Content as TooltipContent, + Portal as TooltipPortal, + Provider as TooltipProvider, + Trigger as TooltipTrigger, + Trigger +}; diff --git a/src/lib/components/ui/tooltip/tooltip-content.svelte b/src/lib/components/ui/tooltip/tooltip-content.svelte new file mode 100644 index 0000000..e4365f3 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,54 @@ + + + + + {@render children?.()} + + {#snippet child({ props })} +
    + {/snippet} +
    +
    +
    diff --git a/src/lib/components/ui/tooltip/tooltip-portal.svelte b/src/lib/components/ui/tooltip/tooltip-portal.svelte new file mode 100644 index 0000000..7d328f0 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/tooltip/tooltip-provider.svelte b/src/lib/components/ui/tooltip/tooltip-provider.svelte new file mode 100644 index 0000000..fde5bb2 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-provider.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/src/lib/components/ui/tooltip/tooltip-trigger.svelte new file mode 100644 index 0000000..0f04162 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/tooltip/tooltip.svelte b/src/lib/components/ui/tooltip/tooltip.svelte new file mode 100644 index 0000000..16eeb70 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/const/schema.ts b/src/lib/const/schema.ts new file mode 100644 index 0000000..4880325 --- /dev/null +++ b/src/lib/const/schema.ts @@ -0,0 +1,35 @@ +import { v } from '$lib'; + +const EnvSchema = v.object({ + CRYPTO_SECRET: v.string(), + DATABASE_URL: v.optional(v.string(), 'file:db.sqlite'), + DISABLE_SIGNUP: v.pipe( + v.optional(v.string(), 'false'), + v.transform((v) => v === 'true') + ), + ENABLE_2FA: v.pipe( + v.optional(v.string(), 'false'), + v.transform((v) => v === 'true') + ), + ENABLE_EMAIL_AND_PASSWORD: v.pipe( + v.optional(v.string(), 'true'), + v.transform((v) => v === 'true') + ), + ORIGIN: v.pipe(v.optional(v.string(), 'http://localhost:5173')), + SMTP_FROM: v.pipe(v.optional(v.string())), + SMTP_HOST: v.pipe(v.optional(v.string())), + SMTP_PASS: v.pipe(v.optional(v.string())), + SMTP_PORT: v.pipe( + v.optional(v.string()), + v.transform((v) => (typeof v === 'string' && !isNaN(parseInt(v)) ? parseInt(v) : undefined)) + ), + SMTP_SSL: v.pipe( + v.optional(v.string()), + v.transform((v) => (v === 'true' ? true : v === 'false' ? false : undefined)) + ), + SMTP_USER: v.pipe(v.optional(v.string())) +}); + +const env = v.parse(EnvSchema, Bun.env); + +export { env }; diff --git a/src/lib/hooks/is-mobile.svelte.ts b/src/lib/hooks/is-mobile.svelte.ts new file mode 100644 index 0000000..acbe8ef --- /dev/null +++ b/src/lib/hooks/is-mobile.svelte.ts @@ -0,0 +1,9 @@ +import { MediaQuery } from 'svelte/reactivity'; + +const DEFAULT_MOBILE_BREAKPOINT = 768; + +export class IsMobile extends MediaQuery { + constructor(breakpoint: number = DEFAULT_MOBILE_BREAKPOINT) { + super(`max-width: ${breakpoint - 1}px`); + } +} diff --git a/src/lib/index.ts b/src/lib/index.ts new file mode 100644 index 0000000..09eb5b6 --- /dev/null +++ b/src/lib/index.ts @@ -0,0 +1,2 @@ +// place files you want to import through the `$lib` alias in this folder. +export * as v from 'valibot'; diff --git a/src/lib/machines/schema.test.ts b/src/lib/machines/schema.test.ts new file mode 100644 index 0000000..1dd825e --- /dev/null +++ b/src/lib/machines/schema.test.ts @@ -0,0 +1,17 @@ +import { expect, test } from 'bun:test'; +import * as v from 'valibot'; + +import { machineSchema } from './schema'; + +test('defaults address when omitted', () => { + const r = v.parse(machineSchema, { name: 'a', token: 't' }); + expect(r.address).toBe('http://127.0.0.1:9999'); +}); + +test('rejects empty name, invalid address, empty token', () => { + expect(v.safeParse(machineSchema, { name: '', token: 't' }).success).toBe(false); + expect(v.safeParse(machineSchema, { address: 'not a url', name: 'a', token: 't' }).success).toBe( + false + ); + expect(v.safeParse(machineSchema, { name: 'a', token: '' }).success).toBe(false); +}); diff --git a/src/lib/machines/schema.ts b/src/lib/machines/schema.ts new file mode 100644 index 0000000..2c2866a --- /dev/null +++ b/src/lib/machines/schema.ts @@ -0,0 +1,30 @@ +import { v } from '$lib'; +import { m } from '$lib/paraglide/messages'; + +const nonEmpty = v.pipe(v.string(m.errors_non_empty()), v.nonEmpty(m.errors_non_empty())); + +const address = v.pipe( + v.optional(v.string(), 'http://127.0.0.1:9999'), + v.transform((s) => s.trim() || 'http://127.0.0.1:9999'), + v.url(m.errors_address_invalid()) +); + +export const machineSchema = v.object({ address, name: nonEmpty, token: nonEmpty }); + +// On edit, any blank field means "keep the existing value" — the server resolves +// it against the current row. Avoids forcing the user to re-paste fields they +// aren't changing. +export const machineEditSchema = v.object({ + address: v.pipe( + v.optional(v.string(), ''), + v.transform((s) => s.trim()) + ), + id: nonEmpty, + name: v.pipe( + v.optional(v.string(), ''), + v.transform((s) => s.trim()) + ), + token: v.optional(v.string(), '') +}); + +export const machineDeleteSchema = v.object({ id: nonEmpty }); diff --git a/src/lib/remotes/auth.remote.ts b/src/lib/remotes/auth.remote.ts new file mode 100644 index 0000000..f8929d2 --- /dev/null +++ b/src/lib/remotes/auth.remote.ts @@ -0,0 +1,109 @@ +import { error, redirect } from '@sveltejs/kit'; +import { form, getRequestEvent, query } from '$app/server'; +import { env as pEnv } from '$env/dynamic/private'; +import { + loginSchema, + registerSchema, + resetPasswordSchema, + resetRequestSchema +} from '$lib/auth/schemas'; +import { auth, oauthConfig } from '$lib/auth/server'; +import { env } from '$lib/const/schema'; +import { m } from '$lib/paraglide/messages'; + +export const getOAuthProviders = query(() => { + const socialProviders = [ + pEnv.FACEBOOK_CLIENT_ID ? 'facebook' : undefined, + pEnv.GITHUB_CLIENT_ID ? 'github' : undefined, + pEnv.GOOGLE_CLIENT_ID ? 'google' : undefined + ].filter((x): x is string => Boolean(x)); + return { oauthConfig, socialProviders }; +}); + +export const login = form(loginSchema, async (credentials) => { + const { request } = getRequestEvent(); + let res: Awaited>; + try { + res = await auth.api.signInUsername({ + body: { + callbackURL: env.ORIGIN + '/dashboard', + password: credentials._password, + rememberMe: credentials.rememberMe, + username: credentials.username + }, + headers: request.headers + }); + } catch (e) { + console.log(e); + + const code = (e as { body?: { code?: string } }).body?.code; + switch (code) { + case 'INVALID_USERNAME_OR_PASSWORD': + throw error(400, { message: m.errors_wrong_credentials() }); + case 'EMAIL_NOT_VERIFIED': + throw error(400, { message: m.verify_your_email() }); + case 'FORBIDDEN': + throw error(401, { message: m.forbidden() }); + default: + throw error(400, { message: m.errors_generic() }); + } + } + if ( + env.ENABLE_2FA && + res?.user !== undefined && + 'twoFactorEnabled' in res.user && + res?.user.twoFactorEnabled !== true + ) + redirect(307, '/auth/setup-2fa'); + if (res && 'twoFactorRedirect' in res) redirect(307, '/auth/2fa'); + redirect(307, '/'); +}); + +export const register = form(registerSchema, async ({ _password, email, username }) => { + const { request } = getRequestEvent(); + try { + await auth.api.signUpEmail({ + body: { email, name: username, password: _password, username }, + headers: request.headers + }); + } catch (e) { + console.log(e); + const code = (e as { body?: { code?: string } }).body?.code; + if (code !== 'USER_ALREADY_EXISTS') throw error(400, { message: m.errors_generic() }); + } + return { email }; +}); + +export const requestReset = form(resetRequestSchema, async ({ email }) => { + await auth.api.requestPasswordReset({ + body: { email, redirectTo: env.ORIGIN + '/auth/reset-password' } + }); + return { sent: true }; +}); + +export const resetPassword = form(resetPasswordSchema, async ({ newPassword, token }) => { + try { + await auth.api.resetPassword({ body: { newPassword, token } }); + } catch (e) { + console.log(e); + throw error(400, { message: m.invalid_reset_link() }); + } + redirect(303, '/auth/sign-in'); +}); + +export const requireUser = query(async () => { + const { + locals: { user } + } = getRequestEvent(); + if (!user) redirect(302, '/auth/sign-in'); + + return user; +}); + +export const getUser = query(async () => { + const { + locals: { user } + } = getRequestEvent(); + + return user; +}); diff --git a/src/lib/remotes/machines.remote.ts b/src/lib/remotes/machines.remote.ts new file mode 100644 index 0000000..22ad056 --- /dev/null +++ b/src/lib/remotes/machines.remote.ts @@ -0,0 +1,61 @@ +import { error } from '@sveltejs/kit'; +import { form, query } from '$app/server'; +import { v } from '$lib'; +import { machineDeleteSchema, machineEditSchema, machineSchema } from '$lib/machines/schema'; +import { m } from '$lib/paraglide/messages'; +import { db } from '$lib/server/db'; +import { machines } from '$lib/server/db/schema'; +import { asc, count, eq, like, or } from 'drizzle-orm'; + +const PAGE_SIZE = 10; + +export const listMachines = query( + v.object({ page: v.optional(v.number(), 1), search: v.optional(v.string(), '') }), + async ({ page, search }) => { + // Never select `token` — it stays server-side only. + const where = search + ? or(like(machines.name, `%${search}%`), like(machines.address, `%${search}%`)) + : undefined; + const [items, totalRows] = await Promise.all([ + db + .select({ address: machines.address, id: machines.id, name: machines.name }) + .from(machines) + .where(where) + .orderBy(asc(machines.name)) + .limit(PAGE_SIZE) + .offset((page - 1) * PAGE_SIZE), + db.select({ total: count() }).from(machines).where(where) + ]); + const total = totalRows[0]?.total ?? 0; + return { items, page, pages: Math.max(1, Math.ceil(total / PAGE_SIZE)), total }; + } +); + +export const addMachine = form(machineSchema, async ({ address, name, token }) => { + await db.insert(machines).values({ address, name, token }); + return { ok: true }; +}); + +export const updateMachine = form(machineEditSchema, async ({ address, id, name, token }) => { + // Only patch the fields the user actually changed — blanks mean "keep current" + // (the form pre-fills name/address but doesn't push them through the form state). + const patch: { address?: string; name?: string; token?: string } = {}; + if (name) patch.name = name; + if (address) { + try { + new URL(address); + } catch { + error(400, { message: m.errors_address_invalid() }); + } + patch.address = address; + } + if (token) patch.token = token; + if (Object.keys(patch).length === 0) return { ok: true }; + await db.update(machines).set(patch).where(eq(machines.id, id)); + return { ok: true }; +}); + +export const deleteMachine = form(machineDeleteSchema, async ({ id }) => { + await db.delete(machines).where(eq(machines.id, id)); + return { ok: true }; +}); diff --git a/src/lib/remotes/server.remote.ts b/src/lib/remotes/server.remote.ts new file mode 100644 index 0000000..0598a9d --- /dev/null +++ b/src/lib/remotes/server.remote.ts @@ -0,0 +1,97 @@ +import { error } from '@sveltejs/kit'; +import { getRequestEvent, query } from '$app/server'; +import { v } from '$lib'; +import { m } from '$lib/paraglide/messages'; +import { db } from '$lib/server/db'; +import { decryptValue } from '$lib/server/db/custom-types'; +import { getClient } from '$lib/server/nadir-agent/client'; + +export const serverInfo = query(async () => { + const { + locals: { user }, + params: { machineId } + } = getRequestEvent(); + if (!user) error(401, { message: m.errors_unauthenticated() }); + const machine = await db.query.machines.findFirst({ where: { id: machineId } }); + if (!machine) error(404, { message: m.errors_not_found() }); + const token = decryptValue(machine.token); + if (!token) error(500, { message: m.errors_generic() }); + const nadir = getClient(machine.address, token); + + const { data, error: err } = await nadir.GET('/api/system/info'); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { token: _, ...safe } = machine; + if (data) return { ...data, $db: safe }; + + throw error(err.status || 500, { message: err.detail || m.errors_generic() }); +}); + +export const auditLog = query(v.optional(v.number(), 20), async (limit) => { + const { + locals: { user }, + params: { machineId } + } = getRequestEvent(); + if (!user) error(401, { message: m.errors_unauthenticated() }); + const machine = await db.query.machines.findFirst({ where: { id: machineId } }); + if (!machine) error(404, { message: m.errors_not_found() }); + const token = decryptValue(machine.token); + if (!token) error(500, { message: m.errors_generic() }); + const nadir = getClient(machine.address, token); + const { data, error: err } = await nadir.GET('/api/audit', { params: { query: { limit } } }); + if (data) return data.entries ?? []; + console.error(err); + throw error(err.status || 500, { message: err.detail || m.errors_generic() }); +}); + +// ponytail: in-memory cache, 10 min; switch to Redis/KV if we ever run >1 node +let latestCache: { at: number; tag: string | null } | null = null; +export const latestAgentRelease = query(async () => { + if (latestCache && Date.now() - latestCache.at < 10 * 60_000) return latestCache.tag; + try { + const r = await fetch( + 'https://tea.urania.dev/api/v1/repos/urania/nadir-agent/releases/latest' + ); + const tag = r.ok ? (((await r.json()) as { tag_name?: string }).tag_name ?? null) : null; + latestCache = { at: Date.now(), tag }; + return tag; + } catch { + return null; + } +}); + +export const systemDetails = query(async () => { + const { + locals: { user }, + params: { machineId } + } = getRequestEvent(); + if (!user) error(401, { message: m.errors_unauthenticated() }); + const machine = await db.query.machines.findFirst({ where: { id: machineId } }); + if (!machine) error(404, { message: m.errors_not_found() }); + const token = decryptValue(machine.token); + if (!token) error(500, { message: m.errors_generic() }); + const nadir = getClient(machine.address, token); + const [time, locale, dns, updates] = await Promise.all([ + nadir.GET('/api/system/time'), + nadir.GET('/api/system/locale'), + nadir.GET('/api/networking/dns'), + nadir.GET('/api/packages/updates') + ]); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { token: _, ...safe } = machine; + return { + $db: safe, + dns: dns.data?.servers ?? null, + locale: locale.data ? { lang: locale.data.lang, vc_keymap: locale.data.vc_keymap } : null, + time: time.data + ? { + local_rtc: time.data.local_rtc, + ntp: time.data.ntp, + ntp_synchronized: time.data.ntp_synchronized, + timezone: time.data.timezone + } + : null, + updates: updates.data + ? { count: updates.data.packages?.length ?? 0, manager: updates.data.manager } + : null + }; +}); diff --git a/src/lib/remotes/users.remote.ts b/src/lib/remotes/users.remote.ts new file mode 100644 index 0000000..b4945be --- /dev/null +++ b/src/lib/remotes/users.remote.ts @@ -0,0 +1,261 @@ +import { error, redirect } from '@sveltejs/kit'; +import { command, form, getRequestEvent, query } from '$app/server'; +import { v } from '$lib'; +import { + banUserSchema, + createUserSchema, + inviteUserSchema, + updateUserSchema +} from '$lib/auth/schemas'; +import { auth } from '$lib/auth/server'; +import { env } from '$lib/const/schema'; +import { m } from '$lib/paraglide/messages'; +import { db } from '$lib/server/db'; +import { + session as sessionTable, + user as userTable, + verification as verificationTable +} from '$lib/server/db/auth-schema'; +import { and, asc, count, desc, eq, gt, gte, inArray, like, lte, max, or, sql } from 'drizzle-orm'; + +type Role = 'admin' | 'user'; + +const requireAdmin = () => { + const { locals } = getRequestEvent(); + if (!locals.user) redirect(307, '/auth/sign-in'); + const roles = (locals.user.role ?? '').split(',').map((r) => r.trim()); + if (!roles.includes('admin')) redirect(307, '/dashboard'); + return locals; +}; + +const withinChoice = v.picklist(['24h', '7d', '30d', 'all']); + +const listInput = v.object({ + activeWithin: v.optional(withinChoice, 'all'), + emailVerifiedOnly: v.optional(v.boolean(), false), + joinedFrom: v.optional(v.string(), ''), + joinedTo: v.optional(v.string(), ''), + joinedWithin: v.optional(withinChoice, 'all'), + limit: v.optional(v.number(), 10), + offset: v.optional(v.number(), 0), + onlineOnly: v.optional(v.boolean(), false), + searchValue: v.optional(v.string(), ''), + showBanned: v.optional(v.boolean(), true), + sortBy: v.optional(v.picklist(['createdAt', 'email', 'name', 'username']), 'createdAt'), + sortDirection: v.optional(v.picklist(['asc', 'desc']), 'desc') +}); + +const withinMs = (k: '24h' | '30d' | '7d' | 'all') => + k === '24h' ? 864e5 : k === '7d' ? 6048e5 : k === '30d' ? 2592e6 : 0; + +export const listUsers = query(listInput, async (input) => { + requireAdmin(); + const now = new Date(); + // ponytail: sweep expired invite tokens — cheap, only runs on admin list view. + await db + .delete(verificationTable) + .where( + and( + like(verificationTable.identifier, 'reset-password:%'), + lte(verificationTable.expiresAt, now) + ) + ); + const conds = []; + + if (input.searchValue) { + const q = `%${input.searchValue}%`; + conds.push(or(like(userTable.email, q), like(userTable.name, q), like(userTable.username, q))); + } + if (!input.showBanned) + conds.push(or(eq(userTable.banned, false), sql`${userTable.banned} IS NULL`)); + if (input.emailVerifiedOnly) conds.push(eq(userTable.emailVerified, true)); + + if (input.joinedWithin !== 'all') { + conds.push(gte(userTable.createdAt, new Date(now.getTime() - withinMs(input.joinedWithin)))); + } + if (input.joinedFrom) conds.push(gte(userTable.createdAt, new Date(input.joinedFrom))); + if (input.joinedTo) conds.push(lte(userTable.createdAt, new Date(input.joinedTo))); + + if (input.onlineOnly) { + conds.push( + inArray( + userTable.id, + db + .select({ id: sessionTable.userId }) + .from(sessionTable) + .where(gt(sessionTable.expiresAt, now)) + ) + ); + } + if (input.activeWithin !== 'all') { + const cutoff = new Date(now.getTime() - withinMs(input.activeWithin)); + conds.push( + inArray( + userTable.id, + db + .select({ id: sessionTable.userId }) + .from(sessionTable) + .where(gte(sessionTable.updatedAt, cutoff)) + ) + ); + } + + const where = conds.length ? and(...conds) : undefined; + const col = userTable[input.sortBy]; + const order = input.sortDirection === 'asc' ? asc(col) : desc(col); + + const totalRow = await db.select({ total: count() }).from(userTable).where(where); + const total = totalRow[0]?.total ?? 0; + const users = await db + .select() + .from(userTable) + .where(where) + .orderBy(order) + .limit(input.limit) + .offset(input.offset); + + // ponytail: attach latest non-expired invite-reset expiry per user (one extra query). + const ids = users.map((u) => u.id); + const invites = ids.length + ? await db + .select({ expiresAt: max(verificationTable.expiresAt), userId: verificationTable.value }) + .from(verificationTable) + .where( + and( + inArray(verificationTable.value, ids), + like(verificationTable.identifier, 'reset-password:%'), + gt(verificationTable.expiresAt, new Date()) + ) + ) + .groupBy(verificationTable.value) + : []; + const inviteMap = new Map(invites.map((i) => [i.userId, i.expiresAt])); + const enriched = users.map((u) => ({ ...u, inviteExpiresAt: inviteMap.get(u.id) ?? null })); + + return { limit: input.limit, offset: input.offset, total, users: enriched }; +}); + +export const createUser = form( + createUserSchema, + async ({ _password, email, name, role, username }) => { + requireAdmin(); + const { request } = getRequestEvent(); + try { + const created = await auth.api.createUser({ + body: { email, name, password: _password, role: role as Role }, + headers: request.headers + }); + // ponytail: admin createUser doesn't accept username; set it after. + if (created?.user?.id && username) { + await db + .update(userTable) + .set({ displayUsername: username, username }) + .where(eq(userTable.id, created.user.id)); + } + return { ok: true }; + } catch (e) { + console.log(e); + const msg = (e as { body?: { message?: string } })?.body?.message || m.errors_generic(); + throw error(400, { message: msg }); + } + } +); + +export const inviteUser = form(inviteUserSchema, async ({ email, name, role, username }) => { + requireAdmin(); + const { request } = getRequestEvent(); + try { + const tmpPassword = crypto.randomUUID() + 'Aa1!'; + const created = await auth.api.createUser({ + body: { email, name: name || email, password: tmpPassword, role: role as Role }, + headers: request.headers + }); + if (created?.user?.id && username) { + await db + .update(userTable) + .set({ displayUsername: username, username }) + .where(eq(userTable.id, created.user.id)); + } + // ponytail: re-use existing reset flow — auth.ts routes /complete-registration → invite email. + await auth.api.requestPasswordReset({ + body: { email, redirectTo: env.ORIGIN + '/auth/complete-registration' } + }); + return { ok: true }; + } catch (e) { + console.log(e); + const msg = (e as { body?: { message?: string } })?.body?.message || m.errors_generic(); + throw error(400, { message: msg }); + } +}); + +export const updateUser = form(updateUserSchema, async ({ email, id, name, role, username }) => { + requireAdmin(); + const { request } = getRequestEvent(); + try { + await auth.api.adminUpdateUser({ + body: { data: { displayUsername: username, email, name, role, username }, userId: id }, + headers: request.headers + }); + return { ok: true }; + } catch (e) { + console.log(e); + const msg = (e as { body?: { message?: string } })?.body?.message || m.errors_generic(); + throw error(400, { message: msg }); + } +}); + +export const deleteUser = command(v.string(), async (id) => { + requireAdmin(); + const { request } = getRequestEvent(); + try { + await auth.api.removeUser({ body: { userId: id }, headers: request.headers }); + } catch (e) { + console.log(e); + throw error(400, { message: m.errors_generic() }); + } +}); + +export const banUser = command(banUserSchema, async ({ banReason, id }) => { + requireAdmin(); + const { request } = getRequestEvent(); + try { + await auth.api.banUser({ + body: { banReason: banReason || 'Banned by admin', userId: id }, + headers: request.headers + }); + } catch (e) { + console.log(e); + throw error(400, { message: m.errors_generic() }); + } +}); + +export const resendInvite = command(v.string(), async (id) => { + requireAdmin(); + const [u] = await db.select().from(userTable).where(eq(userTable.id, id)); + if (!u) throw error(404, { message: m.errors_generic() }); + // Invalidate any prior reset-password tokens for this user. + await db + .delete(verificationTable) + .where( + and(eq(verificationTable.value, id), like(verificationTable.identifier, 'reset-password:%')) + ); + try { + await auth.api.requestPasswordReset({ + body: { email: u.email, redirectTo: env.ORIGIN + '/auth/complete-registration' } + }); + } catch (e) { + console.log(e); + throw error(400, { message: m.errors_generic() }); + } +}); + +export const unbanUser = command(v.string(), async (id) => { + requireAdmin(); + const { request } = getRequestEvent(); + try { + await auth.api.unbanUser({ body: { userId: id }, headers: request.headers }); + } catch (e) { + console.log(e); + throw error(400, { message: m.errors_generic() }); + } +}); diff --git a/src/lib/server/db/auth-schema.ts b/src/lib/server/db/auth-schema.ts new file mode 100644 index 0000000..52561d6 --- /dev/null +++ b/src/lib/server/db/auth-schema.ts @@ -0,0 +1,100 @@ +import { index, integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; + +export const user = sqliteTable('user', { + banExpires: integer('ban_expires', { mode: 'timestamp_ms' }), + banned: integer('banned', { mode: 'boolean' }).default(false), + banReason: text('ban_reason'), + createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(), + displayUsername: text('display_username'), + email: text('email').notNull().unique(), + emailVerified: integer('email_verified', { mode: 'boolean' }).default(false).notNull(), + id: text('id').primaryKey(), + image: text('image'), + name: text('name').notNull(), + role: text('role'), + twoFactorEnabled: integer('two_factor_enabled', { mode: 'boolean' }).default(false), + updatedAt: integer('updated_at', { mode: 'timestamp_ms' }) + .$onUpdate(() => new Date()) + .notNull(), + username: text('username').unique() +}); + +export const session = sqliteTable( + 'session', + { + createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(), + expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(), + id: text('id').primaryKey(), + impersonatedBy: text('impersonated_by'), + ipAddress: text('ip_address'), + token: text('token').notNull().unique(), + updatedAt: integer('updated_at', { mode: 'timestamp_ms' }) + .$onUpdate(() => new Date()) + .notNull(), + userAgent: text('user_agent'), + userId: text('user_id') + .notNull() + .references(() => user.id, { onDelete: 'cascade' }) + }, + (table) => [index('session_userId_idx').on(table.userId)] +); + +export const account = sqliteTable( + 'account', + { + accessToken: text('access_token'), + accessTokenExpiresAt: integer('access_token_expires_at', { + mode: 'timestamp_ms' + }), + accountId: text('account_id').notNull(), + createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(), + id: text('id').primaryKey(), + idToken: text('id_token'), + password: text('password'), + providerId: text('provider_id').notNull(), + refreshToken: text('refresh_token'), + refreshTokenExpiresAt: integer('refresh_token_expires_at', { + mode: 'timestamp_ms' + }), + scope: text('scope'), + updatedAt: integer('updated_at', { mode: 'timestamp_ms' }) + .$onUpdate(() => new Date()) + .notNull(), + userId: text('user_id') + .notNull() + .references(() => user.id, { onDelete: 'cascade' }) + }, + (table) => [index('account_userId_idx').on(table.userId)] +); + +export const verification = sqliteTable( + 'verification', + { + createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull(), + expiresAt: integer('expires_at', { mode: 'timestamp_ms' }).notNull(), + id: text('id').primaryKey(), + identifier: text('identifier').notNull(), + updatedAt: integer('updated_at', { mode: 'timestamp_ms' }) + .$onUpdate(() => new Date()) + .notNull(), + value: text('value').notNull() + }, + (table) => [index('verification_identifier_idx').on(table.identifier)] +); + +export const twoFactor = sqliteTable( + 'two_factor', + { + backupCodes: text('backup_codes').notNull(), + id: text('id').primaryKey(), + secret: text('secret').notNull(), + userId: text('user_id') + .notNull() + .references(() => user.id, { onDelete: 'cascade' }), + verified: integer('verified', { mode: 'boolean' }).default(true) + }, + (table) => [ + index('twoFactor_secret_idx').on(table.secret), + index('twoFactor_userId_idx').on(table.userId) + ] +); diff --git a/src/lib/server/db/custom-types.ts b/src/lib/server/db/custom-types.ts new file mode 100644 index 0000000..6966b9f --- /dev/null +++ b/src/lib/server/db/custom-types.ts @@ -0,0 +1,65 @@ +import { env } from '$lib/const/schema'; +import { customType } from 'drizzle-orm/sqlite-core'; +import crypto from 'node:crypto'; + +const ALGO = 'aes-256-cbc'; +const IV_LENGTH = 16; + +export function decryptValue(encryptedValue: null | string | undefined): null | string { + if (!encryptedValue) return null; + return decrypt(encryptedValue, env.CRYPTO_SECRET); +} + +export function encryptedText(name: string, options: { autoDecrypt: boolean }) { + const { autoDecrypt } = options; + + return customType<{ data: string }>({ + dataType() { + return 'text'; + }, + + fromDriver(value): string { + if (value === null) return ''; + + if (!autoDecrypt) return value as string; + + return decrypt(value as string, env.CRYPTO_SECRET); + }, + + toDriver(value: string): string { + if (value === null) return ''; + + return encrypt(value, env.CRYPTO_SECRET); + } + })(name); +} + +function decrypt(value: string, secret: string) { + const data = Buffer.from(value, 'base64'); + + const iv = data.subarray(0, IV_LENGTH); + const encrypted = data.subarray(IV_LENGTH); + + const key = getKey(secret); + + const decipher = crypto.createDecipheriv(ALGO, key, iv); + + const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]); + + return decrypted.toString('utf8'); +} + +function encrypt(value: string, secret: string) { + const key = getKey(secret); + const iv = crypto.randomBytes(IV_LENGTH); + + const cipher = crypto.createCipheriv(ALGO, key, iv); + + const encrypted = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]); + + return Buffer.concat([iv, encrypted]).toString('base64'); +} + +function getKey(secret: string) { + return crypto.createHash('sha256').update(secret).digest(); +} diff --git a/src/lib/server/db/index.ts b/src/lib/server/db/index.ts new file mode 100644 index 0000000..4f386d9 --- /dev/null +++ b/src/lib/server/db/index.ts @@ -0,0 +1,10 @@ +import { createClient } from '@libsql/client'; +import { env } from '$lib/const/schema'; +import { drizzle } from 'drizzle-orm/libsql'; + +import * as schema from './schema'; +import { relations } from './schema'; + +const client = createClient({ url: env.DATABASE_URL }); + +export const db = drizzle({ client, relations, schema }); diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts new file mode 100644 index 0000000..7352174 --- /dev/null +++ b/src/lib/server/db/schema.ts @@ -0,0 +1,54 @@ +import { defineRelations } from 'drizzle-orm/relations'; +import { int, sqliteTable, text } from 'drizzle-orm/sqlite-core'; + +import { account, session, twoFactor, user } from './auth-schema'; +import { encryptedText } from './custom-types'; + +export const machines = sqliteTable('machines', { + // Full base URL incl. scheme, e.g. https://10.0.0.5:9999 — lets the user pick http/https. + address: text('address').notNull().default('http://127.0.0.1:9999'), + id: text('id') + .primaryKey() + .$defaultFn(() => crypto.randomUUID()) + .notNull(), + name: text('name'), + order: int('order').unique(), + token: encryptedText('token', { autoDecrypt: false }).notNull() +}); + +export const relations = defineRelations( + { + account, + machines, + session, + twoFactor, + user + }, + (r) => ({ + account: { + user: r.one.user({ + from: r.account.userId, + to: r.user.id + }) + }, + session: { + user: r.one.user({ + from: r.session.userId, + to: r.user.id + }) + }, + twoFactor: { + user: r.one.user({ + from: r.twoFactor.userId, + to: r.user.id + }) + }, + user: { + accounts: r.many.account(), + sessions: r.many.session(), + twoFactors: r.many.twoFactor() + } + }) +); + +export * from './auth-schema'; diff --git a/src/lib/server/emails/auth/complete-registration.svelte b/src/lib/server/emails/auth/complete-registration.svelte new file mode 100644 index 0000000..8f80d8f --- /dev/null +++ b/src/lib/server/emails/auth/complete-registration.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/lib/server/emails/auth/layout.svelte b/src/lib/server/emails/auth/layout.svelte new file mode 100644 index 0000000..2329b00 --- /dev/null +++ b/src/lib/server/emails/auth/layout.svelte @@ -0,0 +1,59 @@ + + + + + + + + + +
    + {heading} + + {m.email_greeting({ name })} + + {body} + + {#if buttonLabel && url} + + + {m.email_link_fallback()} + {url} + {/if} + + {@render children?.()} + + {#if footer} + {footer} + {/if} +
    +
    + + diff --git a/src/lib/server/emails/auth/otp.svelte b/src/lib/server/emails/auth/otp.svelte new file mode 100644 index 0000000..0d72755 --- /dev/null +++ b/src/lib/server/emails/auth/otp.svelte @@ -0,0 +1,19 @@ + + + + + {otp} + + diff --git a/src/lib/server/emails/auth/reset-password.svelte b/src/lib/server/emails/auth/reset-password.svelte new file mode 100644 index 0000000..8667176 --- /dev/null +++ b/src/lib/server/emails/auth/reset-password.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/server/emails/auth/verify-email.svelte b/src/lib/server/emails/auth/verify-email.svelte new file mode 100644 index 0000000..dbe3397 --- /dev/null +++ b/src/lib/server/emails/auth/verify-email.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/server/emails/index.ts b/src/lib/server/emails/index.ts new file mode 100644 index 0000000..0635d3e --- /dev/null +++ b/src/lib/server/emails/index.ts @@ -0,0 +1,71 @@ +import { Renderer, toPlainText } from '@better-svelte-email/server'; +import { m } from '$lib/paraglide/messages'; + +import type { MailPayloadInput } from './schemas'; + +import CompleteRegistration from './auth/complete-registration.svelte'; +import Otp from './auth/otp.svelte'; +import ResetPassword from './auth/reset-password.svelte'; +import VerifyEmail from './auth/verify-email.svelte'; +import { sendMail } from './send'; + +type User = { email: string; name: string }; + +const tailwindConfig = { + theme: { + extend: { + colors: { + accent: { DEFAULT: '#82b1ed', foreground: '#fafafa' }, + background: '#fafafa', + border: '#e3e3e3', + card: { DEFAULT: '#fafafa', foreground: '#0a0a0a' }, + destructive: { DEFAULT: '#e7000b', foreground: '#fafafa' }, + foreground: '#0a0a0a', + input: '#e3e3e3', + muted: { DEFAULT: '#f0f0f0', foreground: '#707070' }, + popover: { DEFAULT: '#fafafa', foreground: '#0a0a0a' }, + primary: { DEFAULT: '#5cb3ff', foreground: '#0a0a0a' }, + ring: '#5cb3ff', + secondary: { DEFAULT: '#e1755a', foreground: '#0a0a0a' } + } + } + } +}; + +class Emailer { + #renderer = new Renderer({ tailwindConfig }); + + sendCompleteRegistration = async ({ url, user }: { token: string; url: string; user: User }) => { + const html = await this.#renderer.render(CompleteRegistration, { + props: { name: user.name, url: `${url}` } + }); + return await this.#send({ html, subject: m.email_complete_subject(), to: user.email }); + }; + + sendOtp = async ({ otp, user }: { otp: string; user: User }) => { + const html = await this.#renderer.render(Otp, { + props: { name: user.name, otp } + }); + return await this.#send({ html, subject: m.email_otp_subject(), to: user.email }); + }; + + sendResetPassword = async ({ url, user }: { token: string; url: string; user: User }) => { + const html = await this.#renderer.render(ResetPassword, { + props: { name: user.name, url: `${url}` } + }); + return await this.#send({ html, subject: m.email_reset_subject(), to: user.email }); + }; + + sendVerificationEmail = async ({ url, user }: { url: string; user: User }) => { + const html = await this.#renderer.render(VerifyEmail, { + props: { name: user.name, url } + }); + return await this.#send({ html, subject: m.email_verify_subject(), to: user.email }); + }; + + #send = async ({ html, ...rest }: Omit) => { + await sendMail({ html, plainText: toPlainText(html), ...rest }); + }; +} + +export const emailer = new Emailer(); diff --git a/src/lib/server/emails/schemas.ts b/src/lib/server/emails/schemas.ts new file mode 100644 index 0000000..77e495b --- /dev/null +++ b/src/lib/server/emails/schemas.ts @@ -0,0 +1,11 @@ +import { v } from '$lib'; + +export const MailSchema = v.object({ + html: v.string(), + plainText: v.string(), + subject: v.string(), + to: v.pipe(v.string(), v.email()) +}); + +export type MailPayload = v.InferOutput; +export type MailPayloadInput = v.InferInput; diff --git a/src/lib/server/emails/send.ts b/src/lib/server/emails/send.ts new file mode 100644 index 0000000..ad23ffc --- /dev/null +++ b/src/lib/server/emails/send.ts @@ -0,0 +1,29 @@ +import { env } from '$lib/const/schema'; +import nodemailer from 'nodemailer'; + +import type { MailPayload } from './schemas'; + +// Sends mail directly — no request context, so it's safe from Better Auth background +// tasks that run after the response. Both the Emailer and /api/emailer/send call this. +export async function sendMail(data: MailPayload) { + if (!env.SMTP_HOST) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { html: _html, ...log } = data; + console.log('\n%s\n\n', log.plainText); + return; + } + + const transporter = nodemailer.createTransport({ + auth: { pass: env.SMTP_PASS, user: env.SMTP_USER }, + host: env.SMTP_HOST, + port: env.SMTP_PORT, + secure: env.SMTP_SSL + }); + + await transporter.sendMail({ + from: env.SMTP_FROM, + html: data.html, + subject: data.subject, + to: data.to + }); +} diff --git a/src/lib/server/nadir-agent/client.ts b/src/lib/server/nadir-agent/client.ts new file mode 100644 index 0000000..9206ea5 --- /dev/null +++ b/src/lib/server/nadir-agent/client.ts @@ -0,0 +1,17 @@ +import { getRequestEvent } from '$app/server'; +import createClient from 'openapi-fetch'; + +import type { paths } from './schema'; + +const getClient = (baseUrl: string, token: string) => { + const { fetch } = getRequestEvent(); + return createClient({ + baseUrl: baseUrl, + fetch, + headers: { + authorization: `Bearer ${token}` + } + }); +}; + +export { getClient }; diff --git a/src/lib/server/nadir-agent/schema.d.ts b/src/lib/server/nadir-agent/schema.d.ts new file mode 100644 index 0000000..52757dc --- /dev/null +++ b/src/lib/server/nadir-agent/schema.d.ts @@ -0,0 +1,6306 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + "/api/_modules": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List registered modules + * @description Returns every registered module with its ID, display name, and exported permissions. Public (same static shape as /openapi.json); used by the frontend for navigation and the role/permission matrix. + */ + get: operations["list-modules"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/audit": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List recorded actions + * @description Returns the audit trail of privileged write operations (who, what, when, result), newest first. + */ + get: operations["audit-list"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/groups": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List groups + * @description Returns every group in /etc/group, including system groups (flagged via `system`). + */ + get: operations["groups-list"]; + put?: never; + /** + * Create a group + * @description Creates a group via groupadd. 409 if the group already exists. + */ + post: operations["groups-create"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/groups/{group}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get a single group + * @description Returns one group by name. 404 if it does not exist. + */ + get: operations["groups-get"]; + put?: never; + post?: never; + /** + * Delete a group + * @description Removes a group via groupdel. Returns 409 if it is the primary group of an existing user (groupdel refuses), 404 if it does not exist. + */ + delete: operations["groups-delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/health": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Health check + * @description Public liveness/readiness probe. Reports whether the embedded SQLite session store is reachable. Returns 503 when it is not. + */ + get: operations["health"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/login": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Authenticate and start a session + * @description Verifies the username and password against PAM (the dedicated nadir service) and, on success, sets an HttpOnly session cookie used to authorize all other endpoints. + */ + post: operations["login"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/logout": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * End the current session + * @description Invalidates the session named by the cookie and clears it. Always succeeds, even without a valid session. + */ + post: operations["logout"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/dns": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get configured DNS servers + * @description Returns the nameservers listed in /etc/resolv.conf. DNS is set per-interface as part of the interface config (PUT /api/networking/interfaces/{name}), so there is no standalone DNS write endpoint. + */ + get: operations["networking-get-dns"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/hosts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List /etc/hosts entries + * @description Returns the static host-to-address mappings from /etc/hosts. + */ + get: operations["networking-list-hosts"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/hosts/{ip}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Add or update a /etc/hosts entry + * @description Sets the hostnames for an IP. Replaces the existing line for that IP, or appends a new one; all other lines (comments included) are left untouched. + */ + put: operations["networking-upsert-host"]; + post?: never; + /** + * Remove a /etc/hosts entry + * @description Removes the line(s) mapping the given IP. 404 if no entry exists for it. + */ + delete: operations["networking-delete-host"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/interfaces": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List network interfaces + * @description Returns every interface with its state, MAC, MTU and addresses, via `ip -j addr`. + */ + get: operations["networking-list-interfaces"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/interfaces/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Apply interface configuration + * @description Replaces the interface's IPv4 configuration. The change is applied immediately but starts a rollback timer — if not confirmed within the timeout (default 60s), the prior configuration is automatically restored. This prevents lock-yourself-out mistakes on remote hosts. + */ + put: operations["networking-apply-config"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/interfaces/{name}/confirm": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Confirm a pending change + * @description Cancels the rollback timer, making the applied configuration permanent. + */ + post: operations["networking-confirm-change"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/interfaces/{name}/down": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Take an interface down + * @description Brings the interface down behind the rollback safety net: it is brought back up automatically if not confirmed within the timeout (default 60s). This prevents taking down the link you're managing the host over and losing access. + */ + post: operations["networking-link-down"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/interfaces/{name}/rollback": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Immediately revert a pending change + * @description Reverts the interface to its prior configuration and clears the pending change. + */ + post: operations["networking-rollback-change"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/interfaces/{name}/up": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** Bring an interface up */ + post: operations["networking-link-up"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/pending": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get pending change status + * @description Returns the currently pending change (interface name and seconds until auto-rollback), or 404 if there is no pending change. + */ + get: operations["networking-get-pending"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/networking/routes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List the IPv4 route table + * @description Returns the kernel IPv4 route table via `ip -j route`. + */ + get: operations["networking-list-routes"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/packages": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** List installed packages */ + get: operations["packages-list-installed"]; + put?: never; + /** + * Install a package (streamed) + * @description Installs a package, streaming the package manager's output as `output` events and ending with a `done` event carrying the exit status. + */ + post: operations["packages-install"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/packages/updates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** List available updates */ + get: operations["packages-list-updates"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/packages/upgrade": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Upgrade all packages (streamed) + * @description Upgrades every package to its latest version, streaming the package manager's output live. + */ + post: operations["packages-upgrade"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/packages/{name}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** Remove a package (streamed) */ + delete: operations["packages-remove"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List service units + * @description Returns all service units (active and inactive) via `systemctl list-units --type=service --all`. + */ + get: operations["services-list"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get a service's status + * @description Returns load/active/sub/unit-file state for one unit via `systemctl show`. Returns 404 when the unit does not exist. + */ + get: operations["services-get"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/disable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Disable a service at boot + * @description Disables the unit (`systemctl disable`). Returns 404 when the unit does not exist. + */ + post: operations["services-disable"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/enable": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Enable a service at boot + * @description Enables the unit (`systemctl enable`). Returns 404 when the unit does not exist. + */ + post: operations["services-enable"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get recent log records for a service + * @description Returns a snapshot of the unit's logs from the journal (default) or an allowlisted file (source=file&path=). Use /logs/stream to follow new records live. + */ + get: operations["services-logs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/logs/stream": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Stream a service's logs (Server-Sent Events) + * @description Follows the unit's journal (journalctl -f) or an allowlisted file (source=file&path=, via tail -F) and emits a `log` event per record. Stops when the client disconnects. + */ + get: operations["services-logs-stream"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/restart": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Restart a service + * @description Restarts the unit (`systemctl restart`). Returns 404 when the unit does not exist. + */ + post: operations["services-restart"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/start": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Start a service + * @description Starts the unit (`systemctl start`). Returns 404 when the unit does not exist. + */ + post: operations["services-start"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/services/{unit}/stop": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Stop a service + * @description Stops the unit (`systemctl stop`). Returns 404 when the unit does not exist. + */ + post: operations["services-stop"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/storage/fstab": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List /etc/fstab entries + * @description Returns the persistent mount definitions from /etc/fstab. + */ + get: operations["storage-list-fstab"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/storage/mounts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List active mounts + * @description Returns the kernel mount table (/proc/mounts). + */ + get: operations["storage-list-mounts"]; + put?: never; + /** + * Add and mount a filesystem + * @description Appends an /etc/fstab entry and mounts it. If the mount fails the fstab entry is rolled back, so a bad request leaves the system unchanged. + */ + post: operations["storage-add-mount"]; + /** + * Unmount and remove a filesystem + * @description Unmounts the filesystem (if mounted) and removes its /etc/fstab entry. The mountpoint is passed as a query parameter since it contains slashes. + */ + delete: operations["storage-remove-mount"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/hostname": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get system hostname + * @description Returns the current hostname as reported by hostnamectl. + */ + get: operations["system-get-hostname"]; + put?: never; + /** + * Set system hostname + * @description Sets the static hostname via hostnamectl, which owns /etc/hostname and manages the static/pretty/transient names. + */ + post: operations["system-set-hostname"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/info": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get system information + * @description Returns an overview for a dashboard: OS/kernel identity, CPU, memory and swap, mounted disks, load averages, uptime, network interfaces, and temperatures. All values come from cheap local reads (/proc, /sys, syscalls) with no D-Bus dependency; each section is best-effort. + */ + get: operations["system-get-info"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/keymap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Set virtual console keymap + * @description Sets the virtual console keymap via localectl. The value is validated against the host's keymap list, so an unknown keymap returns 400. + */ + post: operations["system-set-keymap"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/keymaps": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List available console keymaps + * @description Returns every virtual console keymap known to the host. + */ + get: operations["system-list-keymaps"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/locale": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get locale and keyboard layout + * @description Returns the system locale (LANG), virtual console keymap, and X11 layout from localectl. + */ + get: operations["system-get-locale"]; + put?: never; + /** + * Set system locale (LANG) + * @description Sets LANG via localectl. The value is validated against the host's locale list, so an unknown locale returns 400. + */ + post: operations["system-set-locale"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/locales": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List available locales + * @description Returns every locale the host can be configured to use, suitable for populating a selector. + */ + get: operations["system-list-locales"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/ntp": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Enable or disable time synchronization + * @description Toggles network time synchronization via `timedatectl set-ntp`. Selecting specific NTP servers is not yet supported. Returns the resulting time status: on enable, `ntp` is true immediately, but `ntp_synchronized` stays false until the NTP daemon converges (seconds to minutes). + */ + post: operations["system-set-ntp"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/poweroff": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Power off the system + * @description Requires the `root` permission. The response is sent once `shutdown` accepts the request; for the immediate form it returns before the machine actually goes down, so a 200 does not guarantee a clean shutdown completed. + */ + post: operations["system-poweroff"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/reboot": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Reboot the system + * @description Requires the `root` permission. The response is sent once `shutdown` accepts the request; for the immediate form it returns before the machine actually goes down, so a 200 does not guarantee a clean shutdown completed. + */ + post: operations["system-reboot"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/time": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get time, timezone and sync status + * @description Returns the current UTC time plus timezone and synchronization state from timedatectl. + */ + get: operations["system-get-time"]; + put?: never; + /** + * Set system time manually + * @description Sets the clock to an explicit RFC3339 time. This only works when NTP is disabled; otherwise timedatectl refuses and the call returns 409. + */ + post: operations["system-set-time"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/timezone": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Set system timezone + * @description Sets the timezone via timedatectl. The value is validated against the host's timezone list, so an unknown name returns 400. + */ + post: operations["system-set-timezone"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/system/timezones": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List available timezones + * @description Returns every IANA timezone name known to the host, suitable for populating a selector. + */ + get: operations["system-list-timezones"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/terminal": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Connect to an interactive terminal + * @description Upgrades the connection to a WebSocket and spawns a PTY shell as the logged-in user. Send JSON `{cols, rows}` text messages to resize, and raw binary/text messages for stdin. This is a raw WebSocket endpoint — it cannot be exercised from the API docs "Try it" panel; use a WebSocket client. + */ + get: operations["terminal-connect"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * List user accounts + * @description Returns every account in /etc/passwd, including system accounts (flagged via `system`). + */ + get: operations["users-list"]; + put?: never; + /** + * Create a user account + * @description Creates an account via useradd. The new account has a locked password until one is set via the password endpoint. 409 if the user already exists. + */ + post: operations["users-create"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{username}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get a single user + * @description Returns one account by login name. 404 if it does not exist. + */ + get: operations["users-get"]; + put?: never; + post?: never; + /** + * Delete a user account + * @description Removes an account via userdel. Pass ?remove_home=true to also delete the home directory. 404 if the user does not exist. + */ + delete: operations["users-delete"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{username}/groups": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * Set a user's supplementary groups + * @description Replaces the user's full supplementary group set via `usermod -G` (an empty list removes them from all supplementary groups). Returns the resulting group membership. 404 if the user does not exist; 400 if any named group is missing. Requires the `root` permission: adding an account to wheel/sudo/docker is a privilege grant, not a routine write. + */ + put: operations["users-set-groups"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/{username}/password": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Set a user's password + * @description Sets the password via chpasswd (fed over stdin, so the secret never appears in the process list). 404 if the user does not exist. Requires the `root` permission: resetting a privileged account's password (e.g. root) is a full-system action, not a routine write. + */ + post: operations["users-set-password"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/whoami": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Get the current user and their permissions + * @description Returns the authenticated username and, per module, the permissions the caller holds (wildcards resolved). Pair with /api/_modules to render the full permission matrix. + */ + get: operations["whoami"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + ApplyOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ApplyOutputBody.json + */ + readonly $schema?: string; + /** + * @description Network backend that applied the change + * @example nmcli + */ + backend: string; + /** @example eth0 */ + interface: string; + /** + * Format: int64 + * @description Seconds until auto-rollback unless confirmed + * @example 60 + */ + rollback_seconds: number; + /** + * @description Always "pending" — confirm to make permanent + * @example pending + */ + status: string; + }; + AuditListOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/AuditListOutputBody.json + */ + readonly $schema?: string; + /** @description Recorded actions, newest first */ + entries: components["schemas"]["Entry"][] | null; + }; + CPUInfo: { + /** + * Format: int64 + * @description Peak current clock across all cores (instantaneous snapshot; 0 if cpufreq unavailable) + * @example 3157 + */ + current_mhz: number; + /** + * Format: int64 + * @description Number of logical CPUs (cores × threads) + * @example 16 + */ + logical_cpus: number; + /** + * Format: int64 + * @description Highest frequency (boost ceiling) + * @example 5137 + */ + max_mhz: number; + /** + * Format: int64 + * @description Lowest frequency the scaling governor can select + * @example 400 + */ + min_mhz: number; + /** + * @description CPU model name + * @example AMD Ryzen 7 7840U + */ + model: string; + }; + CoreUsage: { + /** + * Format: int64 + * @description Logical core index + * @example 0 + */ + core: number; + /** + * Format: double + * @description Usage percentage (0–100) + * @example 23.4 + */ + usage_pct: number; + }; + CreateGroupInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/CreateGroupInputBody.json + */ + readonly $schema?: string; + /** + * Format: int64 + * @description Explicit GID (omit to auto-assign) + * @example 1500 + */ + gid?: number; + /** + * @description Group name + * @example developers + */ + name: string; + /** @description Create a system group (groupadd --system) */ + system?: boolean; + }; + CreateUserInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/CreateUserInputBody.json + */ + readonly $schema?: string; + /** + * @description GECOS comment + * @example Alice Smith + */ + comment?: string; + /** @description Create the home directory (useradd -m) */ + create_home?: boolean; + /** + * @description Home directory (defaults to /home/) + * @example /home/alice + */ + home?: string; + /** + * @description Login shell + * @example /bin/bash + */ + shell?: string; + /** @description Create a system account (useradd --system) */ + system?: boolean; + /** + * @description Login name + * @example alice + */ + username: string; + }; + DNSOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/DNSOutputBody.json + */ + readonly $schema?: string; + /** + * @description Nameservers from /etc/resolv.conf + * @example [ + * "1.1.1.1" + * ] + */ + servers: string[] | null; + }; + DiskInfo: { + /** + * @description Backing device + * @example /dev/nvme0n1p2 + */ + filesystem: string; + /** + * Format: int64 + * @description Space available to unprivileged users + * @example 256000000000 + */ + free_bytes: number; + /** @example btrfs */ + fstype: string; + /** @example / */ + mountpoint: string; + /** + * Format: int64 + * @example 512000000000 + */ + total_bytes: number; + /** + * Format: int64 + * @example 256000000000 + */ + used_bytes: number; + }; + Entry: { + /** + * @description HTTP method + * @example POST + */ + method: string; + /** + * @description Target module + * @example users + */ + module: string; + /** + * @description Request path + * @example /api/users + */ + path: string; + /** + * Format: int64 + * @description HTTP response status + * @example 200 + */ + status: number; + /** + * @description When the action occurred (RFC3339, UTC) + * @example 2026-06-20T08:15:04Z + */ + time: string; + /** + * @description Who performed it + * @example alice + */ + username: string; + }; + ErrorDetail: { + /** @description Where the error occurred, e.g. 'body.items[3].tags' or 'path.thing-id' */ + location?: string; + /** @description Error message text */ + message?: string; + /** @description The value at the given location */ + value?: unknown; + }; + ErrorEvent: { + message: string; + }; + ErrorModel: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ErrorModel.json + */ + readonly $schema?: string; + /** + * @description A human-readable explanation specific to this occurrence of the problem. + * @example Property foo is required but is missing. + */ + detail?: string; + /** @description Optional list of individual error details */ + errors?: components["schemas"]["ErrorDetail"][] | null; + /** + * Format: uri + * @description A URI reference that identifies the specific occurrence of the problem. + * @example https://example.com/error-log/abc123 + */ + instance?: string; + /** + * Format: int64 + * @description HTTP status code + * @example 400 + */ + status?: number; + /** + * @description A short, human-readable summary of the problem type. This value should not change between occurrences of the error. + * @example Bad Request + */ + title?: string; + /** + * Format: uri + * @description A URI reference to human-readable documentation for the error. + * @default about:blank + * @example https://example.com/errors/example + */ + type: string; + }; + FstabEntry: { + /** @example UUID=1234-5678 */ + device: string; + /** + * Format: int64 + * @example 0 + */ + dump: number; + /** @example ext4 */ + fstype: string; + /** @example /mnt/data */ + mountpoint: string; + /** @example defaults */ + options: string; + /** + * Format: int64 + * @description fsck order (0 = skip) + * @example 2 + */ + pass: number; + }; + Group: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/Group.json + */ + readonly $schema?: string; + /** + * Format: int64 + * @description Group ID + * @example 10 + */ + gid: number; + /** @description Supplementary members (primary-group members are not listed here) */ + members: string[] | null; + /** + * @description Group name + * @example wheel + */ + name: string; + /** @description True for system groups (gid < 1000) */ + system: boolean; + }; + HealthOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/HealthOutputBody.json + */ + readonly $schema?: string; + /** + * @description Embedded SQLite session store state + * @example ok + */ + database: string; + /** + * @description Overall health + * @example ok + */ + status: string; + }; + HostEntry: { + /** + * @description Names mapped to the address + * @example [ + * "server", + * "server.local" + * ] + */ + hostnames: string[] | null; + /** + * @description IPv4 or IPv6 address + * @example 192.168.1.10 + */ + ip: string; + }; + HostUpsertInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/HostUpsertInputBody.json + */ + readonly $schema?: string; + /** + * @description Names to map to the IP + * @example [ + * "server", + * "server.local" + * ] + */ + hostnames: string[] | null; + }; + HostnameBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/HostnameBody.json + */ + readonly $schema?: string; + /** + * @description System hostname + * @example server01 + */ + hostname: string; + }; + IPv6Config: { + /** + * @description IPv6 address (static only) + * @example 2001:db8::10 + */ + address?: string; + /** + * @description IPv6 default gateway (static only, optional) + * @example 2001:db8::1 + */ + gateway?: string; + /** + * @description "auto" (SLAAC), "static", or "ignore" (disable IPv6) + * @example static + * @enum {string} + */ + method: "auto" | "static" | "ignore"; + /** + * Format: int64 + * @description Prefix length (static only) + * @example 64 + */ + prefix?: number; + }; + IfaceConfig: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/IfaceConfig.json + */ + readonly $schema?: string; + /** + * @description IPv4 address (static only) + * @example 192.168.1.10 + */ + address?: string; + /** + * @description DNS servers for this interface (IPv4 or IPv6) + * @example [ + * "1.1.1.1", + * "8.8.8.8" + * ] + */ + dns?: string[] | null; + /** + * @description Default gateway (static only, optional) + * @example 192.168.1.1 + */ + gateway?: string; + /** @description Optional IPv6 settings. Omit to leave IPv6 untouched; include to manage it. */ + ipv6?: components["schemas"]["IPv6Config"]; + /** + * @description "static" for a fixed address, "dhcp" for automatic + * @example static + * @enum {string} + */ + method: "static" | "dhcp"; + /** + * Format: int64 + * @description Network prefix length (static only) + * @example 24 + */ + prefix?: number; + /** + * Format: int64 + * @description Auto-revert after this many seconds unless confirmed. 0 uses the default (60s). + * @example 60 + */ + rollback_seconds?: number; + /** @description Static routes to install for this interface */ + routes?: components["schemas"]["Route"][] | null; + }; + InstallInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/InstallInputBody.json + */ + readonly $schema?: string; + /** + * @description Package to install + * @example htop + */ + name: string; + }; + Interface: { + /** + * @description IPv4 addresses in CIDR form + * @example [ + * "192.168.1.10/24" + * ] + */ + ipv4: string[] | null; + /** + * @description IPv6 addresses in CIDR form + * @example [ + * "fe80::1/64" + * ] + */ + ipv6: string[] | null; + /** @example 52:54:00:12:34:56 */ + mac: string; + /** + * Format: int64 + * @example 1500 + */ + mtu: number; + /** @example eth0 */ + name: string; + /** + * @description operstate: up / down / unknown + * @example up + */ + state: string; + }; + KeymapsOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/KeymapsOutputBody.json + */ + readonly $schema?: string; + /** @description Available virtual console keymaps */ + keymaps: string[] | null; + }; + ListFstabOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListFstabOutputBody.json + */ + readonly $schema?: string; + entries: components["schemas"]["FstabEntry"][] | null; + }; + ListGroupsOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListGroupsOutputBody.json + */ + readonly $schema?: string; + /** @description All groups from /etc/group */ + groups: components["schemas"]["Group"][] | null; + }; + ListHostsOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListHostsOutputBody.json + */ + readonly $schema?: string; + entries: components["schemas"]["HostEntry"][] | null; + }; + ListInterfacesOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListInterfacesOutputBody.json + */ + readonly $schema?: string; + interfaces: components["schemas"]["Interface"][] | null; + }; + ListMountsOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListMountsOutputBody.json + */ + readonly $schema?: string; + mounts: components["schemas"]["Mount"][] | null; + }; + ListOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListOutputBody.json + */ + readonly $schema?: string; + /** + * @description Detected package manager + * @example dnf + */ + manager: string; + packages: components["schemas"]["Package"][] | null; + }; + ListRoutesOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListRoutesOutputBody.json + */ + readonly $schema?: string; + routes: components["schemas"]["RouteEntry"][] | null; + }; + ListServicesOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListServicesOutputBody.json + */ + readonly $schema?: string; + /** @description All service units, active and inactive */ + services: components["schemas"]["ServiceUnit"][] | null; + }; + ListUsersOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ListUsersOutputBody.json + */ + readonly $schema?: string; + /** @description All accounts from /etc/passwd */ + users: components["schemas"]["User"][] | null; + }; + LoadInfo: { + /** @description Per-core CPU usage percentage (sampled over ~1 s); empty until the first sample completes */ + cpu_usage: components["schemas"]["CoreUsage"][] | null; + /** + * Format: double + * @example 0.42 + */ + load1: number; + /** + * Format: double + * @example 0.61 + */ + load15: number; + /** + * Format: double + * @example 0.55 + */ + load5: number; + }; + LocaleStatusBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/LocaleStatusBody.json + */ + readonly $schema?: string; + /** + * @description System locale (LANG) + * @example it_IT.UTF-8 + */ + lang: string; + /** + * @description Virtual console keymap + * @example it + */ + vc_keymap: string; + /** + * @description X11 keyboard layout + * @example it + */ + x11_layout: string; + }; + LocalesOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/LocalesOutputBody.json + */ + readonly $schema?: string; + /** @description Available locales */ + locales: string[] | null; + }; + LogEntry: { + /** @example Started OpenSSH server daemon. */ + message: string; + /** + * Format: int64 + * @description syslog priority 0 (emerg) – 7 (debug); 6 for file lines + * @example 6 + */ + priority: number; + /** + * @description Record timestamp (RFC3339, UTC); empty for file lines + * @example 2026-06-20T08:15:04Z + */ + time: string; + }; + LoginInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/LoginInputBody.json + */ + readonly $schema?: string; + /** @description System password */ + password: string; + /** @description System username */ + username: string; + }; + LoginOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/LoginOutputBody.json + */ + readonly $schema?: string; + /** @example logged in */ + status: string; + }; + LogoutOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/LogoutOutputBody.json + */ + readonly $schema?: string; + /** @example logged out */ + status: string; + }; + LogsOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/LogsOutputBody.json + */ + readonly $schema?: string; + /** @description Log records, oldest first */ + entries: components["schemas"]["LogEntry"][] | null; + }; + MemoryInfo: { + /** + * Format: int64 + * @description Memory available for new allocations without swapping + * @example 8192000000 + */ + available_bytes: number; + /** + * Format: int64 + * @example 8589934592 + */ + swap_free_bytes: number; + /** + * Format: int64 + * @example 8589934592 + */ + swap_total_bytes: number; + /** + * Format: int64 + * @example 16384000000 + */ + total_bytes: number; + /** + * Format: int64 + * @description total - available + * @example 8192000000 + */ + used_bytes: number; + }; + ModuleInfo: { + /** + * @description Stable module identifier + * @example system + */ + id: string; + /** + * @description Human-readable module name + * @example System + */ + name: string; + /** @description Permissions this module exposes (never includes the "*" wildcard) */ + permissions: string[] | null; + }; + ModulesOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ModulesOutputBody.json + */ + readonly $schema?: string; + /** @description Registered modules, sorted by ID */ + modules: components["schemas"]["ModuleInfo"][] | null; + }; + Mount: { + /** @example /dev/sda1 */ + device: string; + /** @example ext4 */ + fstype: string; + /** @example /mnt/data */ + mountpoint: string; + /** @example rw,relatime */ + options: string; + }; + MountInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/MountInputBody.json + */ + readonly $schema?: string; + /** + * @description Block device or UUID=/LABEL= specifier + * @example /dev/sdb1 + */ + device: string; + /** Format: int64 */ + dump?: number; + /** @example ext4 */ + fstype: string; + /** + * @description Absolute mount path + * @example /mnt/data + */ + mountpoint: string; + /** + * @description Mount options (default: defaults) + * @example defaults + */ + options?: string; + /** + * Format: int64 + * @description fsck order (default 2 for real filesystems, 0 to skip) + */ + pass?: number; + }; + NetInterface: { + /** @description Assigned addresses in CIDR notation */ + addresses: string[] | null; + /** @example aa:bb:cc:dd:ee:ff */ + mac: string; + /** @example eth0 */ + name: string; + /** @description Interface is administratively up */ + up: boolean; + }; + OSInfo: { + /** + * @description Machine hardware architecture (uname -m) + * @example x86_64 + */ + architecture: string; + /** + * @description System hostname + * @example server01 + */ + hostname: string; + /** + * @description Running kernel release (uname -r) + * @example 7.0.12-201.fc44.x86_64 + */ + kernel: string; + /** + * @description Distro name from /etc/os-release PRETTY_NAME + * @example Fedora Linux 44 (Workstation Edition) + */ + pretty_name: string; + }; + Package: { + /** + * @description Package name + * @example openssh-server + */ + name: string; + /** + * @description Installed version, or the available version for updates + * @example 9.6p1 + */ + version: string; + }; + PendingInfo: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/PendingInfo.json + */ + readonly $schema?: string; + /** + * @description Interface with a pending change + * @example eth0 + */ + interface: string; + /** + * Format: int64 + * @description Seconds until auto-rollback + * @example 45 + */ + seconds_remaining: number; + }; + PkgDoneEvent: { + /** @description Exit error when it failed */ + error?: string; + /** @description True if the package manager exited 0 */ + success: boolean; + }; + PkgErrorEvent: { + message: string; + }; + PkgOutputEvent: { + /** @description One line of the package manager's terminal output */ + line: string; + }; + PowerInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/PowerInputBody.json + */ + readonly $schema?: string; + /** + * @description When to act, as a shutdown(8) TIME (e.g. "+5" minutes, "23:00"). Empty or 'now' = immediate. + * @example +1 + */ + when?: string; + }; + Route: { + /** + * @description Destination network in CIDR notation, or "default" + * @example 10.0.0.0/24 + */ + destination: string; + /** + * @description Next-hop gateway + * @example 192.168.1.1 + */ + gateway: string; + }; + RouteEntry: { + /** + * @description Destination network, or "default" + * @example default + */ + destination: string; + /** @example 192.168.1.1 */ + gateway?: string; + /** @example eth0 */ + interface: string; + /** + * Format: int64 + * @example 100 + */ + metric?: number; + /** + * @description Preferred source address + * @example 192.168.1.10 + */ + source?: string; + }; + ServiceStatusBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/ServiceStatusBody.json + */ + readonly $schema?: string; + /** + * @description active / inactive / failed + * @example active + */ + active_state: string; + /** @example OpenSSH server daemon */ + description: string; + /** + * @description loaded / not-found / masked + * @example loaded + */ + load_state: string; + /** @example running */ + sub_state: string; + /** @example sshd.service */ + unit: string; + /** + * @description enabled / disabled / static + * @example enabled + */ + unit_file_state: string; + }; + ServiceUnit: { + /** + * @description High-level active state + * @example active + */ + active: string; + /** + * @description Unit description + * @example OpenSSH server daemon + */ + description: string; + /** + * @description Load state + * @example loaded + */ + load: string; + /** + * @description Low-level sub state + * @example running + */ + sub: string; + /** + * @description Unit name + * @example sshd.service + */ + unit: string; + }; + SetGroupsInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetGroupsInputBody.json + */ + readonly $schema?: string; + /** @description Supplementary groups; replaces the user's full supplementary set */ + groups: string[] | null; + }; + SetKeymapInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetKeymapInputBody.json + */ + readonly $schema?: string; + /** + * @description Virtual console keymap + * @example it + */ + keymap: string; + }; + SetLocaleInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetLocaleInputBody.json + */ + readonly $schema?: string; + /** + * @description Locale to set as LANG + * @example it_IT.UTF-8 + */ + lang: string; + }; + SetNTPInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetNTPInputBody.json + */ + readonly $schema?: string; + /** @description Enable network time synchronization */ + enabled: boolean; + }; + SetPasswordInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetPasswordInputBody.json + */ + readonly $schema?: string; + /** @description New password (sent to chpasswd over stdin, never argv) */ + password: string; + }; + SetTimeInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetTimeInputBody.json + */ + readonly $schema?: string; + /** + * @description New time (RFC3339). Requires NTP disabled. + * @example 2026-06-19T13:36:31Z + */ + time: string; + }; + SetTimezoneInputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SetTimezoneInputBody.json + */ + readonly $schema?: string; + /** + * @description IANA timezone name + * @example Europe/Rome + */ + timezone: string; + }; + StatusOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/StatusOutputBody.json + */ + readonly $schema?: string; + /** + * @description Always "ok" on success + * @example ok + */ + status: string; + }; + SystemInfoBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/SystemInfoBody.json + */ + readonly $schema?: string; + /** + * @description Boot time (RFC3339, UTC) + * @example 2026-06-19T12:08:00Z + */ + boot_time: string; + /** @description Processor model and core count */ + cpu: components["schemas"]["CPUInfo"]; + /** @description Mounted block-device filesystems */ + disks: components["schemas"]["DiskInfo"][] | null; + /** @description Load averages (1/5/15 min) */ + load: components["schemas"]["LoadInfo"]; + /** @description RAM and swap usage in bytes */ + memory: components["schemas"]["MemoryInfo"]; + /** @description Network interfaces and their addresses */ + network_interfaces: components["schemas"]["NetInterface"][] | null; + /** @description OS and kernel identity */ + os: components["schemas"]["OSInfo"]; + /** @description Thermal sensor readings in Celsius */ + temperatures: components["schemas"]["Temperature"][] | null; + /** + * Format: int64 + * @description Seconds since boot + * @example 12490 + */ + uptime_seconds: number; + }; + Temperature: { + /** + * Format: double + * @example 47.5 + */ + celsius: number; + /** + * @description hwmon chip name; identifies the source (k10temp/coretemp=CPU, amdgpu/nvidia=GPU, nvme=disk) + * @example k10temp + */ + chip: string; + /** + * @description Per-sensor label, or the chip name when the sensor is unlabelled + * @example Tctl + */ + label: string; + }; + TimeStatusBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/TimeStatusBody.json + */ + readonly $schema?: string; + /** @description An NTP service is available on this host */ + can_ntp: boolean; + /** @description Hardware clock kept in local time instead of UTC */ + local_rtc: boolean; + /** @description Network time synchronization enabled */ + ntp: boolean; + /** @description Clock is currently synchronized */ + ntp_synchronized: boolean; + /** + * @description Current system time (RFC3339, UTC) + * @example 2026-06-19T13:36:31Z + */ + time: string; + /** + * @description IANA timezone name + * @example Europe/Rome + */ + timezone: string; + }; + TimezonesOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/TimezonesOutputBody.json + */ + readonly $schema?: string; + /** @description Available IANA timezone names */ + timezones: string[] | null; + }; + User: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/User.json + */ + readonly $schema?: string; + /** + * @description GECOS comment (often the full name) + * @example Alice Smith + */ + comment: string; + /** + * Format: int64 + * @description Primary group ID + * @example 1000 + */ + gid: number; + /** + * @description Home directory + * @example /home/alice + */ + home: string; + /** + * @description Login shell + * @example /bin/bash + */ + shell: string; + /** @description True for system accounts (uid < 1000) */ + system: boolean; + /** + * Format: int64 + * @description User ID + * @example 1000 + */ + uid: number; + /** + * @description Login name + * @example alice + */ + username: string; + }; + UserGroupsOutputBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/UserGroupsOutputBody.json + */ + readonly $schema?: string; + /** @description All groups the user belongs to (primary + supplementary) */ + groups: string[] | null; + /** @example alice */ + username: string; + }; + WhoamiBody: { + /** + * Format: uri + * @description A URL to the JSON Schema for this object. + * @example https://example.com/schemas/WhoamiBody.json + */ + readonly $schema?: string; + /** @description Module ID -> permissions the caller holds. Modules where they hold none are omitted. */ + permissions: { + [key: string]: string[] | null; + }; + /** + * @description Authenticated username + * @example urania + */ + username: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export interface operations { + "list-modules": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ModulesOutputBody"]; + }; + }; + /** @description Error */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "audit-list": { + parameters: { + query?: { + /** @description Max entries to return, newest first */ + limit?: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["AuditListOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "groups-list": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListGroupsOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "groups-create": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateGroupInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Group"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "groups-get": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Group name */ + group: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Group"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "groups-delete": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Group name */ + group: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + health: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HealthOutputBody"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Service Unavailable */ + 503: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + login: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["LoginInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + "Set-Cookie"?: string; + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LoginOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Too Many Requests */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + logout: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: { + nadir_session_id?: string; + }; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + "Set-Cookie"?: string; + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LogoutOutputBody"]; + }; + }; + /** @description Error */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-get-dns": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["DNSOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-list-hosts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListHostsOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-upsert-host": { + parameters: { + query?: never; + header?: never; + path: { + /** @description IP address to add or update */ + ip: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["HostUpsertInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Implemented */ + 501: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-delete-host": { + parameters: { + query?: never; + header?: never; + path: { + /** @description IP address whose entry to remove */ + ip: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-list-interfaces": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListInterfacesOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-apply-config": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Interface name */ + name: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["IfaceConfig"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ApplyOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Implemented */ + 501: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-confirm-change": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Interface name */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Implemented */ + 501: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-link-down": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Interface name */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ApplyOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Implemented */ + 501: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-rollback-change": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Interface name */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Implemented */ + 501: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-link-up": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Interface name */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Implemented */ + 501: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-get-pending": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["PendingInfo"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "networking-list-routes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListRoutesOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "packages-list-installed": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "packages-install": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["InstallInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/event-stream": ({ + data: components["schemas"]["PkgDoneEvent"]; + /** + * @description The event name. + * @constant + */ + event: "done"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["PkgErrorEvent"]; + /** + * @description The event name. + * @constant + */ + event: "error"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["PkgOutputEvent"]; + /** + * @description The event name. + * @constant + */ + event: "output"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + })[]; + }; + }; + /** @description Error */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "packages-list-updates": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "packages-upgrade": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/event-stream": ({ + data: components["schemas"]["PkgDoneEvent"]; + /** + * @description The event name. + * @constant + */ + event: "done"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["PkgErrorEvent"]; + /** + * @description The event name. + * @constant + */ + event: "error"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["PkgOutputEvent"]; + /** + * @description The event name. + * @constant + */ + event: "output"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + })[]; + }; + }; + /** @description Error */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "packages-remove": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Package to remove */ + name: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/event-stream": ({ + data: components["schemas"]["PkgDoneEvent"]; + /** + * @description The event name. + * @constant + */ + event: "done"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["PkgErrorEvent"]; + /** + * @description The event name. + * @constant + */ + event: "error"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["PkgOutputEvent"]; + /** + * @description The event name. + * @constant + */ + event: "output"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + })[]; + }; + }; + /** @description Error */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-list": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListServicesOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-get": { + parameters: { + query?: never; + header?: never; + path: { + /** @description systemd unit name */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ServiceStatusBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-disable": { + parameters: { + query?: never; + header?: never; + path: { + /** @description systemd unit name */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-enable": { + parameters: { + query?: never; + header?: never; + path: { + /** @description systemd unit name */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-logs": { + parameters: { + query?: { + /** @description Where to read logs from */ + source?: "journal" | "file"; + /** @description Log file (file source only); must be allowlisted for this unit in config */ + path?: string; + /** @description How many recent records to return (max 10000) */ + lines?: number; + /** @description journalctl time filter (journal source only) */ + since?: string; + /** @description Max syslog priority to include: 0 emerg .. 7 debug (journal source only). 7 = all. */ + priority?: number; + }; + header?: never; + path: { + /** @description Unit name as listed by GET /api/services; the trailing .service is optional */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LogsOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-logs-stream": { + parameters: { + query?: { + /** @description Where to stream logs from */ + source?: "journal" | "file"; + /** @description Log file (file source only); must be allowlisted for this unit in config */ + path?: string; + /** @description Backfill window (journal source only) */ + since?: string; + /** @description Max syslog priority to include: 0 emerg .. 7 debug (journal source only). 7 = all. */ + priority?: number; + }; + header?: never; + path: { + /** @description Unit name as listed by GET /api/services; the trailing .service is optional */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "text/event-stream": ({ + data: components["schemas"]["ErrorEvent"]; + /** + * @description The event name. + * @constant + */ + event: "error"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + } | { + data: components["schemas"]["LogEntry"]; + /** + * @description The event name. + * @constant + */ + event: "log"; + /** @description The event ID. */ + id?: number; + /** @description The retry time in milliseconds. */ + retry?: number; + })[]; + }; + }; + /** @description Error */ + default: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-restart": { + parameters: { + query?: never; + header?: never; + path: { + /** @description systemd unit name */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-start": { + parameters: { + query?: never; + header?: never; + path: { + /** @description systemd unit name */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "services-stop": { + parameters: { + query?: never; + header?: never; + path: { + /** @description systemd unit name */ + unit: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "storage-list-fstab": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListFstabOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "storage-list-mounts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListMountsOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "storage-add-mount": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["MountInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "storage-remove-mount": { + parameters: { + query?: { + /** @description Mountpoint to unmount and remove from fstab */ + mountpoint?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-get-hostname": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["HostnameBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-set-hostname": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["HostnameBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-get-info": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["SystemInfoBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-set-keymap": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetKeymapInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-list-keymaps": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["KeymapsOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-get-locale": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LocaleStatusBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-set-locale": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetLocaleInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-list-locales": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["LocalesOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-set-ntp": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetNTPInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TimeStatusBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-poweroff": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PowerInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-reboot": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["PowerInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-get-time": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TimeStatusBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-set-time": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetTimeInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-set-timezone": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetTimezoneInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "system-list-timezones": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["TimezonesOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "terminal-connect": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description No Content */ + 204: { + headers: { + [name: string]: unknown; + }; + content?: never; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Upgrade Required */ + 426: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "users-list": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["ListUsersOutputBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "users-create": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CreateUserInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["User"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "users-get": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Login name */ + username: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["User"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "users-delete": { + parameters: { + query?: { + /** @description Also remove the home directory and mail spool (userdel -r) */ + remove_home?: boolean; + }; + header?: never; + path: { + /** @description Login name */ + username: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "users-set-groups": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Login name */ + username: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetGroupsInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["UserGroupsOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Conflict */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + "users-set-password": { + parameters: { + query?: never; + header?: never; + path: { + /** @description Login name */ + username: string; + }; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SetPasswordInputBody"]; + }; + }; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["StatusOutputBody"]; + }; + }; + /** @description Bad Request */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Forbidden */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Not Found */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; + whoami: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: { + nadir_session_id?: string; + }; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["WhoamiBody"]; + }; + }; + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Unprocessable Entity */ + 422: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + /** @description Internal Server Error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/problem+json": components["schemas"]["ErrorModel"]; + }; + }; + }; + }; +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..deea172 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,13 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export type WithElementRef = { ref?: null | U } & T; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChild = T extends { child?: any } ? Omit : T; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChildren = T extends { children?: any } ? Omit : T; +export type WithoutChildrenOrChild = WithoutChildren>; +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..f896c38 --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,55 @@ + + + + + + {@const currentUser = await user} + {#if currentUser} + + {/if} + + {#if await user} +
    + + + +
    + +
    +
    + {/if} +
    + {@render children()} +
    +
    +
    + +
    + {#each locales as locale (locale)} + {locale} + {/each} +
    + + + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte new file mode 100644 index 0000000..cc88df0 --- /dev/null +++ b/src/routes/+page.svelte @@ -0,0 +1,2 @@ +

    Welcome to SvelteKit

    +

    Visit svelte.dev/docs/kit to read the documentation

    diff --git a/src/routes/admin/+layout.server.ts b/src/routes/admin/+layout.server.ts new file mode 100644 index 0000000..4db612b --- /dev/null +++ b/src/routes/admin/+layout.server.ts @@ -0,0 +1,3 @@ +// Forces hooks.server.ts to run on every /admin navigation (client-side router +// skips the server otherwise when no server load is defined). +export const load = () => {}; diff --git a/src/routes/admin/+page.svelte b/src/routes/admin/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/admin/config/+page.svelte b/src/routes/admin/config/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/admin/users/+page.svelte b/src/routes/admin/users/+page.svelte new file mode 100644 index 0000000..0929177 --- /dev/null +++ b/src/routes/admin/users/+page.svelte @@ -0,0 +1,721 @@ + + +
    +
    +
    +

    {m.users_title()}

    +

    {m.users_description()}

    +
    +
    + + + {#snippet child({ props })} + + {/snippet} + + +
    +

    {m.users_filter_title()}

    +
    +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    +
    + +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + + +
    +
    + +
    + {m.users_rows_per_page()} + { + const n = Number((e.target as HTMLInputElement).value); + if (n >= 1) { + pageSize.current = n; + page = 1; + } + }} + /> + + {#each [10, 20, 50, 100] as n (n)} + + {/each} + +
    +
    +
    + + {m.users_filter_count({ n: activeFilterCount })} +
    +
    +
    + +
    + + + + {#snippet child({ props })} + + {/snippet} + + + (createOpen = true)} + >{m.users_create()} + (inviteOpen = true)} + >{m.users_invite()} + + +
    +
    +
    + +
    + +
    + +
    + + + + {#each [{ key: 'name', label: m.name() }, { key: 'username', label: m.username() }, { key: 'email', label: m.email() }, { key: 'createdAt', label: m.users_created_at() }] as col (col.key)} + + + + {/each} + {m.users_role()} + {m.users_status()} + {m.users_actions()} + + + + {#if usersQuery.loading && !data.users.length} + + + + {:else if !data.users.length} + + {m.users_no_results()} + + {:else} + {#each data.users as u (u.id)} + + {u.name} + {u.username ?? '—'} + {u.email} + {new Date(u.createdAt).toLocaleDateString()} + + + {u.role === 'admin' ? m.users_role_admin() : m.users_role_user()} + + + + {#if u.banned} + {m.users_banned()} + {:else if !u.emailVerified} + + {m.users_pending()} + + {:else} + {m.users_active()} + {/if} + + + + + {#snippet child({ props })} + + {/snippet} + + + openEdit(u)} + >{m.users_edit()} + {#if !u.emailVerified} + doResendInvite(u)} + >{m.users_resend_invite()} + {/if} + toggleBan(u)}> + {u.banned ? m.users_unban() : m.users_ban()} + + + openDelete(u)}> + {m.users_delete()} + + + + + + {/each} + {/if} + + +
    + +
    +
    + {m.users_page_of({ page, total: totalPages })} + + +
    +
    +
    + + + + + + {m.users_create_title()} + {m.users_create_description()} + +
    createUser.validate()} + {...createUser.preflight(createUserSchema).enhance(async ({ submit }) => { + try { + await submit(); + toast.success(m.users_created()); + createOpen = false; + } catch (e) { + handleError(e); + } + })} + > + + + {m.name()} + + {#each createUser.fields.name.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.username()} + + {#each createUser.fields.username.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.email()} + + {#each createUser.fields.email.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.password()} + + {#each createUser.fields._password.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.users_role()} + + + + + + + + + + +
    +
    +
    + + + + + + {m.users_edit_title()} + {m.users_edit_description()} + + {#if editing} +
    updateUser.validate()} + {...updateUser.preflight(updateUserSchema).enhance(async ({ submit }) => { + try { + await submit(); + toast.success(m.users_saved()); + editOpen = false; + editing = null; + } catch (e) { + handleError(e); + } + })} + > + + + + {m.name()} + + {#each updateUser.fields.name.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.username()} + + {#each updateUser.fields.username.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.email()} + + {#each updateUser.fields.email.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.users_role()} + + + + + + + + + + +
    + {/if} +
    +
    + + + + + + {m.users_delete_confirm_title()} + {m.users_delete_confirm_description()} + + {#if deleting && !deleting.banned} +
    + + {#if alsoBan} + + {/if} +
    + {/if} + + {m.cancel()} + {m.users_delete()} + +
    +
    + + + + + + {m.users_invite_title()} + {m.users_invite_description()} + +
    inviteUser.validate()} + {...inviteUser.preflight(inviteUserSchema).enhance(async ({ submit }) => { + try { + await submit(); + toast.success(m.users_invited()); + inviteOpen = false; + } catch (e) { + handleError(e); + } + })} + > + + + {m.email()} + + {#each inviteUser.fields.email.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.name()} + + + + {m.username()} + + + + {m.users_role()} + + + + + + + + + + +
    +
    +
    diff --git a/src/routes/api/emailer/send/+server.ts b/src/routes/api/emailer/send/+server.ts new file mode 100644 index 0000000..7a02c0f --- /dev/null +++ b/src/routes/api/emailer/send/+server.ts @@ -0,0 +1,23 @@ +import { json } from '@sveltejs/kit'; +import { v } from '$lib'; +import { MailSchema } from '$lib/server/emails/schemas'; +import { sendMail } from '$lib/server/emails/send'; + +export const POST = async ({ request }) => { + let data: v.InferOutput; + try { + data = v.parse(MailSchema, await request.json()); + } catch (err) { + console.error(err); + return json({ ok: false }); + } + + try { + await sendMail(data); + } catch (err) { + console.error(err); + return json({ ok: false }); + } + + return json({ ok: true }); +}; diff --git a/src/routes/auth/+layout.svelte b/src/routes/auth/+layout.svelte new file mode 100644 index 0000000..89c0010 --- /dev/null +++ b/src/routes/auth/+layout.svelte @@ -0,0 +1,23 @@ + + +
    +
    + +
    + +
    +

    {m.appname()}

    +
    + {@render children()} +
    +
    diff --git a/src/routes/auth/2fa/+page.svelte b/src/routes/auth/2fa/+page.svelte new file mode 100644 index 0000000..e280fd5 --- /dev/null +++ b/src/routes/auth/2fa/+page.svelte @@ -0,0 +1,91 @@ + + + + + {m.two_factor_title()} + {m.two_factor_description()} + + +
    + + + {backup ? m.backup_code() : m.code()} + {#if backup} + + {:else} + + {#snippet children({ cells })} + + {#each cells.slice(0, 3) as cell (cell)} + + {/each} + + + + {#each cells.slice(3, 6) as cell (cell)} + + {/each} + + {/snippet} + + {/if} + + + + {m.trust_device()} + + + + + + + + +
    +
    +
    diff --git a/src/routes/auth/forgot-password/+page.svelte b/src/routes/auth/forgot-password/+page.svelte new file mode 100644 index 0000000..9ba9a60 --- /dev/null +++ b/src/routes/auth/forgot-password/+page.svelte @@ -0,0 +1,62 @@ + + + + + {m.forgot_password_title()} + + {requestReset.result?.sent ? m.reset_link_sent() : m.forgot_password_description()} + + + + {#if requestReset.result?.sent} + + {:else} +
    requestReset.validate()} + {...requestReset.preflight(resetRequestSchema).enhance(async ({ submit }) => { + try { + await submit(); + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + + {m.email()} + + {#each requestReset.fields.email.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + + + {m.back_to_login()} + + + +
    + {/if} +
    +
    diff --git a/src/routes/auth/reset-password/+page.svelte b/src/routes/auth/reset-password/+page.svelte new file mode 100644 index 0000000..e0aeaa0 --- /dev/null +++ b/src/routes/auth/reset-password/+page.svelte @@ -0,0 +1,72 @@ + + + + + {m.reset_password_title()} + + {token ? m.reset_password_description() : m.invalid_reset_link()} + + + + {#if token} +
    resetPassword.validate()} + {...resetPassword.preflight(resetPasswordSchema).enhance(async ({ submit }) => { + try { + await submit(); + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + + + {m.new_password()} + + {#each resetPassword.fields.newPassword.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.confirm_password()} + + {#each resetPassword.fields._confirm.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + {m.password_hint()} + + + + + +
    + {:else} + + {/if} +
    +
    diff --git a/src/routes/auth/setup-2fa/+page.svelte b/src/routes/auth/setup-2fa/+page.svelte new file mode 100644 index 0000000..350d815 --- /dev/null +++ b/src/routes/auth/setup-2fa/+page.svelte @@ -0,0 +1,162 @@ + + + + + {m.setup_2fa_title()} + + {step === 'password' ? m.setup_2fa_description() : m.scan_qr()} + + + + {#if step === 'password'} +
    + + + {m.enter_password_to_continue()} + + + + + + +
    + {:else} +
    + +
    +
    + + {@html renderSVG(totpURI)} +
    +
    + {m.manual_entry_key()} + + {secret} + +
    +
    + + +
    +
    +
    + {m.backup_codes_title()} +
    + {m.backup_codes_notice()} +
    + {#each backupCodes as backupCode (backupCode)} + {backupCode} + {/each} +
    +
    + + + {m.code()} + + {#snippet children({ cells })} + + {#each cells.slice(0, 3) as cell (cell)} + + {/each} + + + + {#each cells.slice(3, 6) as cell (cell)} + + {/each} + + {/snippet} + + + +
    +
    + {/if} +
    +
    diff --git a/src/routes/auth/sign-in/+page.svelte b/src/routes/auth/sign-in/+page.svelte new file mode 100644 index 0000000..e54230e --- /dev/null +++ b/src/routes/auth/sign-in/+page.svelte @@ -0,0 +1,132 @@ + + +
    + + + {m.welcome_back()} + {m.login_social_description()} + + +
    login.validate()} + {...login.preflight(loginSchema).enhance(async ({ submit }) => { + try { + await submit(); + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + {#each providers.socialProviders as provider (provider)} + + + + {/each} + {#each providers.oauthConfig as provider (provider.providerId)} + + + + {/each} + {#if providers.oauthConfig.length || providers.socialProviders.length} + + {m.or()} + + {/if} + + {m.username()} + + {#each login.fields.username.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + +
    + {m.password()} + + {m.forgot_password()} + +
    + + {#each login.fields._password.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} +
    + + + {m.remember_me()} + + + + + {m.no_account()} {m.sign_up()} + + +
    +
    +
    +
    + + + {@html m.terms_notice({ privacy: '/privacy-policy', terms: '/terms-of-service' })} + +
    diff --git a/src/routes/auth/sign-up/+page.svelte b/src/routes/auth/sign-up/+page.svelte new file mode 100644 index 0000000..1cf1a02 --- /dev/null +++ b/src/routes/auth/sign-up/+page.svelte @@ -0,0 +1,98 @@ + + +{#if register.result?.email} + + + {m.check_your_email()} + {m.verification_sent({ email: register.result.email })} + + + + + +{:else} + + + {m.sign_up_title()} + {m.sign_up_description()} + + +
    register.validate()} + {...register.preflight(registerSchema).enhance(async ({ submit }) => { + try { + await submit(); + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + + {m.username()} + + {#each register.fields.username.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.email()} + + {#each register.fields.email.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.password()} + + {#each register.fields._password.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.confirm_password()} + + {#each register.fields._confirm.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + {m.password_hint()} + + + + + {m.already_have_account()} + {m.login()} + + + +
    +
    +
    +{/if} diff --git a/src/routes/dashboard/+page.svelte b/src/routes/dashboard/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/dashboard/[machineId]/+page.svelte b/src/routes/dashboard/[machineId]/+page.svelte new file mode 100644 index 0000000..4d56bde --- /dev/null +++ b/src/routes/dashboard/[machineId]/+page.svelte @@ -0,0 +1,380 @@ + + +
    + + {#snippet failed(err)} + {console.log('errore', err)} + {/snippet} + + {@const sys = await info} + {@const log = await audit} + {@const d = await details} + {@const latestTag = await latest} + {@const agentVersion = (sys as unknown as { agent_version?: string }).agent_version} + {@const outdated = !!(agentVersion && latestTag && agentVersion !== latestTag)} + {@const memPct = pct(sys.memory.used_bytes, sys.memory.total_bytes)} + {@const loadPct = Math.round((sys.load.load1 / sys.cpu.logical_cpus) * 100)} + {@const swapPct = pct( + sys.memory.swap_total_bytes - sys.memory.swap_free_bytes, + sys.memory.swap_total_bytes + )} + +
    +
    +

    {sys.$db.name}

    +

    + {sys.os.hostname} | {sys.os.pretty_name} | {sys.$db.address} +

    +
    +
    + + {intervalLabel} + + {#each intervals as opt (opt.value)} + {opt.label} + {/each} + + + {#if syncInterval === 'custom'} +
    + +
    + {/if} + + + + + {#snippet child({ props })} + + {/snippet} + + + (editOpen = true)}> + + {m.edit()} + + (deleteOpen = true)}> + + {m.delete()} + + + +
    +
    + +
    + + + + + {#snippet extra()} +
    + {gb(sys.memory.used_bytes)} / {gb(sys.memory.total_bytes)} +
    + + {#if sys.memory.swap_total_bytes > 0} +
    + {gb(sys.memory.swap_total_bytes - sys.memory.swap_free_bytes)} / {gb( + sys.memory.swap_total_bytes + )} + {m.dashboard_swap({ swapPct })} +
    + + {/if} + {/snippet} +
    + + + + +
    +
    +
    + +
    + + +
    + +
    + + + +
    + +
    + +
    + + + + + {m.machine_edit()} + {m.machine_edit_description()} + +
    updateMachine.validate()} + {...updateMachine.preflight(machineEditSchema).enhance(async ({ submit }) => { + try { + await submit(); + await Promise.all([ + listMachines({ page: 1, search: '' }).refresh(), + info.refresh(), + details.refresh() + ]); + editOpen = false; + toast.success(m.machine_edit()); + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + + + {m.machine_name()} + + {#each updateMachine.fields.name.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.machine_address()} + + {#each updateMachine.fields.address.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + {m.machine_token()} + + {m.machine_token_keep()} + {#each updateMachine.fields.token.issues() as issue, i (`${issue}-${i}`)} + {issue.message} + {/each} + + + +
    +
    +
    + + + + + {m.machine_delete_title()} + + {m.machine_delete_confirm({ name: sys.$db.name ?? '' })} + + + + {m.cancel()} +
    { + try { + await submit(); + await listMachines({ page: 1, search: '' }).refresh(); + deleteOpen = false; + goto(resolve('/dashboard')); + } catch (error) { + console.error(error); + toast.error( + (error as { body?: { message?: string } })?.body?.message || m.errors_generic() + ); + } + })} + > + + + {m.delete()} + +
    +
    +
    +
    +
    +
    diff --git a/src/routes/layout.css b/src/routes/layout.css new file mode 100644 index 0000000..c0d2047 --- /dev/null +++ b/src/routes/layout.css @@ -0,0 +1,171 @@ +@import 'tailwindcss'; +@import 'tw-animate-css'; +@import 'shadcn-svelte/tailwind.css'; + +@custom-variant dark (&:is(.dark *)); + +:root { + --theme-light: oklch(0.985 0 0); + --theme-dark: oklch(0.145 0 0); + --theme-primary: oklch(75% 0.15 250); + --theme-secondary: oklch(0.68 0.14 35); + --theme-tertiary: oklch(75% 0.1 255); + + --background: var(--theme-light); + --foreground: var(--theme-dark); + --card: oklch(from var(--theme-light) l c h / 100%); + --card-foreground: var(--theme-dark); + --popover: oklch(from var(--theme-light) l c h / 100%); + --popover-foreground: var(--theme-dark); + --primary: var(--theme-primary); + --primary-foreground: var(--theme-dark); + --secondary: var(--theme-secondary); + --secondary-foreground: var(--theme-dark); + --tertiary: var(--theme-tertiary); + --tertiary-foreground: var(--theme-dark); + --accent: var(--theme-tertiary); + --accent-foreground: var(--theme-dark); + --muted: oklch(from var(--theme-light) calc(l - 0.03) c h); + --muted-foreground: oklch(from var(--theme-dark) calc(l + 0.4) c h); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(from var(--theme-light) calc(l - 0.07) c h); + --input: oklch(from var(--theme-light) calc(l - 0.07) c h); + --ring: var(--theme-primary); + --chart-1: var(--theme-primary); + --chart-2: var(--theme-secondary); + --chart-3: var(--theme-tertiary); + --chart-4: oklch(from var(--theme-primary) calc(l - 0.15) c h); + --chart-5: oklch(from var(--theme-secondary) calc(l - 0.15) c h); + --radius: 0.25rem; + --sidebar: oklch(from var(--theme-light) calc(l - 0.01) c h); + --sidebar-foreground: var(--theme-dark); + --sidebar-primary: var(--theme-primary); + --sidebar-primary-foreground: var(--theme-light); + --sidebar-accent: var(--theme-secondary); + --sidebar-accent-foreground: var(--theme-dark); + --sidebar-border: var(--border); + --sidebar-ring: var(--ring); +} + +.dark { + --background: var(--theme-dark); + --foreground: var(--theme-light); + --card: oklch(from var(--theme-dark) calc(l + 0.06) c h); + --card-foreground: var(--theme-light); + --popover: oklch(from var(--theme-dark) calc(l + 0.06) c h); + --popover-foreground: var(--theme-light); + --primary: var(--theme-primary); + --primary-foreground: var(--theme-dark); + --secondary: var(--theme-secondary); + --secondary-foreground: var(--theme-dark); + --accent: var(--theme-tertiary); + --accent-foreground: var(--theme-dark); + --muted: oklch(from var(--theme-dark) calc(l + 0.12) c h); + --muted-foreground: oklch(from var(--theme-light) calc(l - 0.3) c h); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(from var(--theme-dark) calc(l + 0.125) c h / 30%); + --input: oklch(from var(--theme-dark) calc(l + 0.25) c h / 100%); + --ring: var(--theme-primary); + --chart-1: var(--theme-primary); + --chart-2: var(--theme-secondary); + --chart-3: var(--theme-tertiary); + --chart-4: oklch(from var(--theme-primary) calc(l + 0.1) c h); + --chart-5: oklch(from var(--theme-secondary) calc(l + 0.1) c h); + --sidebar: oklch(from var(--theme-dark) calc(l + 0.04) c h); + --sidebar-foreground: var(--theme-light); + --sidebar-primary: var(--theme-primary); + --sidebar-primary-foreground: var(--theme-light); + --sidebar-accent: var(--theme-secondary); + --sidebar-accent-foreground: var(--theme-dark); + --sidebar-border: var(--border); + --sidebar-ring: var(--ring); +} + +@theme inline { + --font-sans: 'Work Sans', sans-serif; + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-tertiary: var(--tertiary); + --color-tertiary-foreground: var(--tertiary-foreground); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --color-foreground: var(--foreground); + --color-background: var(--background); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } + html { + @apply font-sans; + } + + .link { + @apply font-medium decoration-inherit decoration-2 underline-offset-1!; + } + + ::selection { + @apply bg-primary text-background; + } + + ::-webkit-scrollbar { + @apply h-2 w-2; + } + + ::-webkit-scrollbar-track { + @apply border-s border-border bg-background; + } + + ::-webkit-scrollbar-thumb { + @apply bg-muted; + } + + input:-webkit-autofill, + textarea:-webkit-autofill, + select:-webkit-autofill { + -webkit-box-shadow: 0 0 0 1000px hsl(var(--background)) inset !important; + box-shadow: 0 0 0 1000px hsl(var(--background)) inset !important; + -webkit-text-fill-color: hsl(var(--foreground)) !important; + } + input:-webkit-autofill, + textarea:-webkit-autofill, + select:-webkit-autofill { + -webkit-background-clip: text; + } +} diff --git a/src/routes/system/+page.svelte b/src/routes/system/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/system/date-time/+page.svelte b/src/routes/system/date-time/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/system/localization/+page.svelte b/src/routes/system/localization/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/static/robots.txt b/static/robots.txt new file mode 100644 index 0000000..b6dd667 --- /dev/null +++ b/static/robots.txt @@ -0,0 +1,3 @@ +# allow crawling everything by default +User-agent: * +Disallow: diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..06bbb1b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "rewriteRelativeImportExtensions": true, + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "noUncheckedIndexedAccess": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "module": "esnext", + "moduleResolution": "bundler", + "types": ["bun", "node"] + } + // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias + // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files + // + // To make changes to top-level options such as include and exclude, we recommend extending + // the generated config; see https://svelte.dev/docs/kit/configuration#typescript +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..3fbcf72 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,30 @@ +import { paraglideVitePlugin } from '@inlang/paraglide-js'; +import adapter from '@sveltejs/adapter-node'; +import { sveltekit } from '@sveltejs/kit/vite'; +import tailwindcss from '@tailwindcss/vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [ + tailwindcss(), + sveltekit({ + adapter: adapter(), + compilerOptions: { + experimental: { async: true }, + runes: ({ filename }) => + filename.split(/[/\\]/).includes('node_modules') ? undefined : true + }, + experimental: { remoteFunctions: true }, + typescript: { + config: (config) => ({ + ...config, + include: [...config.include, '../drizzle.config.ts'] + }) + } + }), + paraglideVitePlugin({ outdir: './src/lib/paraglide', project: './project.inlang' }) + ], + server: { + allowedHosts: [process.env.ALLOWED_HOST || 'localhost:5173'] + } +});