From 2c2f33ea687807987a4603b41523712faa3472c7 Mon Sep 17 00:00:00 2001 From: Bradley Shellnut Date: Tue, 31 Dec 2024 22:43:09 +0000 Subject: [PATCH] Initial commit --- .env.example | 15 + .eslintignore | 13 + .gitignore | 10 + .node-version | 1 + .npmrc | 1 + .prettierignore | 4 + .prettierrc | 8 + .vscode/settings.json | 3 + Dockerfile.minio | 3 + README.md | 111 + components.json | 14 + docker-compose.yaml | 58 + drizzle.config.ts | 16 + eslint.config.js | 33 + minio-console.conf.template | 41 + package.json | 90 + playwright.config.ts | 12 + pnpm-lock.yaml | 7388 +++++++++++++++++ postcss.config.js | 6 + render.yaml | 101 + src/app.css | 78 + src/app.d.ts | 30 + src/app.html | 12 + src/hooks.server.ts | 42 + src/index.test.ts | 7 + src/lib/components/container.svelte | 15 + src/lib/components/pin-input.svelte | 32 + .../ui/accordion/accordion-content.svelte | 25 + .../ui/accordion/accordion-item.svelte | 14 + .../ui/accordion/accordion-trigger.svelte | 26 + src/lib/components/ui/accordion/index.ts | 17 + .../alert-dialog/alert-dialog-action.svelte | 21 + .../alert-dialog/alert-dialog-cancel.svelte | 21 + .../alert-dialog/alert-dialog-content.svelte | 28 + .../alert-dialog-description.svelte | 16 + .../alert-dialog/alert-dialog-footer.svelte | 16 + .../alert-dialog/alert-dialog-header.svelte | 13 + .../alert-dialog/alert-dialog-overlay.svelte | 21 + .../alert-dialog/alert-dialog-portal.svelte | 9 + .../ui/alert-dialog/alert-dialog-title.svelte | 14 + src/lib/components/ui/alert-dialog/index.ts | 40 + .../ui/alert/alert-description.svelte | 13 + .../components/ui/alert/alert-title.svelte | 21 + src/lib/components/ui/alert/alert.svelte | 17 + src/lib/components/ui/alert/index.ts | 33 + .../ui/aspect-ratio/aspect-ratio.svelte | 11 + src/lib/components/ui/aspect-ratio/index.ts | 3 + .../ui/avatar/avatar-fallback.svelte | 16 + .../components/ui/avatar/avatar-image.svelte | 18 + src/lib/components/ui/avatar/avatar.svelte | 18 + src/lib/components/ui/avatar/index.ts | 13 + src/lib/components/ui/badge/badge.svelte | 18 + src/lib/components/ui/badge/index.ts | 21 + .../ui/breadcrumb/breadcrumb-ellipsis.svelte | 24 + .../ui/breadcrumb/breadcrumb-item.svelte | 16 + .../ui/breadcrumb/breadcrumb-link.svelte | 31 + .../ui/breadcrumb/breadcrumb-list.svelte | 23 + .../ui/breadcrumb/breadcrumb-page.svelte | 23 + .../ui/breadcrumb/breadcrumb-separator.svelte | 25 + .../ui/breadcrumb/breadcrumb.svelte | 15 + src/lib/components/ui/breadcrumb/index.ts | 25 + src/lib/components/ui/button/button.svelte | 25 + src/lib/components/ui/button/index.ts | 49 + .../ui/calendar/calendar-cell.svelte | 21 + .../ui/calendar/calendar-day.svelte | 42 + .../ui/calendar/calendar-grid-body.svelte | 13 + .../ui/calendar/calendar-grid-head.svelte | 13 + .../ui/calendar/calendar-grid-row.svelte | 13 + .../ui/calendar/calendar-grid.svelte | 13 + .../ui/calendar/calendar-head-cell.svelte | 16 + .../ui/calendar/calendar-header.svelte | 16 + .../ui/calendar/calendar-heading.svelte | 19 + .../ui/calendar/calendar-months.svelte | 16 + .../ui/calendar/calendar-next-button.svelte | 27 + .../ui/calendar/calendar-prev-button.svelte | 27 + .../components/ui/calendar/calendar.svelte | 59 + src/lib/components/ui/calendar/index.ts | 30 + .../components/ui/card/card-content.svelte | 13 + .../ui/card/card-description.svelte | 13 + src/lib/components/ui/card/card-footer.svelte | 13 + src/lib/components/ui/card/card-header.svelte | 13 + src/lib/components/ui/card/card-title.svelte | 21 + src/lib/components/ui/card/card.svelte | 16 + src/lib/components/ui/card/index.ts | 24 + .../ui/carousel/carousel-content.svelte | 35 + .../ui/carousel/carousel-item.svelte | 25 + .../ui/carousel/carousel-next.svelte | 39 + .../ui/carousel/carousel-previous.svelte | 40 + .../components/ui/carousel/carousel.svelte | 98 + src/lib/components/ui/carousel/context.ts | 56 + src/lib/components/ui/carousel/index.ts | 5 + .../components/ui/checkbox/checkbox.svelte | 35 + src/lib/components/ui/checkbox/index.ts | 6 + .../ui/collapsible/collapsible-content.svelte | 15 + src/lib/components/ui/collapsible/index.ts | 15 + .../ui/command/command-dialog.svelte | 23 + .../ui/command/command-empty.svelte | 12 + .../ui/command/command-group.svelte | 18 + .../ui/command/command-input.svelte | 23 + .../components/ui/command/command-item.svelte | 24 + .../components/ui/command/command-list.svelte | 15 + .../ui/command/command-separator.svelte | 10 + .../ui/command/command-shortcut.svelte | 16 + src/lib/components/ui/command/command.svelte | 22 + src/lib/components/ui/command/index.ts | 37 + .../context-menu-checkbox-item.svelte | 35 + .../context-menu/context-menu-content.svelte | 24 + .../ui/context-menu/context-menu-item.svelte | 31 + .../ui/context-menu/context-menu-label.svelte | 19 + .../context-menu-radio-group.svelte | 11 + .../context-menu-radio-item.svelte | 35 + .../context-menu-separator.svelte | 14 + .../context-menu/context-menu-shortcut.svelte | 16 + .../context-menu-sub-content.svelte | 29 + .../context-menu-sub-trigger.svelte | 32 + src/lib/components/ui/context-menu/index.ts | 49 + .../ui/dialog/dialog-content.svelte | 36 + .../ui/dialog/dialog-description.svelte | 16 + .../components/ui/dialog/dialog-footer.svelte | 16 + .../components/ui/dialog/dialog-header.svelte | 13 + .../ui/dialog/dialog-overlay.svelte | 21 + .../components/ui/dialog/dialog-portal.svelte | 8 + .../components/ui/dialog/dialog-title.svelte | 16 + src/lib/components/ui/dialog/index.ts | 37 + .../ui/drawer/drawer-content.svelte | 24 + .../ui/drawer/drawer-description.svelte | 18 + .../components/ui/drawer/drawer-footer.svelte | 16 + .../components/ui/drawer/drawer-header.svelte | 19 + .../components/ui/drawer/drawer-nested.svelte | 12 + .../ui/drawer/drawer-overlay.svelte | 18 + .../components/ui/drawer/drawer-title.svelte | 18 + src/lib/components/ui/drawer/drawer.svelte | 12 + src/lib/components/ui/drawer/index.ts | 41 + .../dropdown-menu-checkbox-item.svelte | 35 + .../dropdown-menu-content.svelte | 27 + .../dropdown-menu/dropdown-menu-item.svelte | 31 + .../dropdown-menu/dropdown-menu-label.svelte | 19 + .../dropdown-menu-radio-group.svelte | 11 + .../dropdown-menu-radio-item.svelte | 35 + .../dropdown-menu-separator.svelte | 14 + .../dropdown-menu-shortcut.svelte | 13 + .../dropdown-menu-sub-content.svelte | 30 + .../dropdown-menu-sub-trigger.svelte | 32 + src/lib/components/ui/dropdown-menu/index.ts | 48 + src/lib/components/ui/form/form-button.svelte | 10 + .../ui/form/form-description.svelte | 17 + .../ui/form/form-element-field.svelte | 25 + .../ui/form/form-field-errors.svelte | 26 + src/lib/components/ui/form/form-field.svelte | 25 + .../components/ui/form/form-fieldset.svelte | 30 + src/lib/components/ui/form/form-label.svelte | 17 + src/lib/components/ui/form/form-legend.svelte | 17 + src/lib/components/ui/form/index.ts | 33 + .../ui/hover-card/hover-card-content.svelte | 27 + src/lib/components/ui/hover-card/index.ts | 14 + src/lib/components/ui/input/index.ts | 29 + src/lib/components/ui/input/input.svelte | 42 + src/lib/components/ui/label/index.ts | 7 + src/lib/components/ui/label/label.svelte | 21 + src/lib/components/ui/menubar/index.ts | 52 + .../ui/menubar/menubar-checkbox-item.svelte | 35 + .../ui/menubar/menubar-content.svelte | 33 + .../components/ui/menubar/menubar-item.svelte | 31 + .../ui/menubar/menubar-label.svelte | 19 + .../ui/menubar/menubar-radio-item.svelte | 35 + .../ui/menubar/menubar-separator.svelte | 11 + .../ui/menubar/menubar-shortcut.svelte | 16 + .../ui/menubar/menubar-sub-content.svelte | 27 + .../ui/menubar/menubar-sub-trigger.svelte | 32 + .../ui/menubar/menubar-trigger.svelte | 23 + src/lib/components/ui/menubar/menubar.svelte | 16 + src/lib/components/ui/pagination/index.ts | 25 + .../ui/pagination/pagination-content.svelte | 13 + .../ui/pagination/pagination-ellipsis.svelte | 19 + .../ui/pagination/pagination-item.svelte | 13 + .../ui/pagination/pagination-link.svelte | 34 + .../pagination/pagination-next-button.svelte | 27 + .../pagination/pagination-prev-button.svelte | 27 + .../ui/pagination/pagination.svelte | 33 + src/lib/components/ui/popover/index.ts | 17 + .../ui/popover/popover-content.svelte | 22 + src/lib/components/ui/progress/index.ts | 7 + .../components/ui/progress/progress.svelte | 21 + src/lib/components/ui/radio-group/index.ts | 15 + .../ui/radio-group/radio-group-item.svelte | 28 + .../ui/radio-group/radio-group.svelte | 14 + src/lib/components/ui/range-calendar/index.ts | 30 + .../range-calendar/range-calendar-cell.svelte | 21 + .../range-calendar/range-calendar-day.svelte | 43 + .../range-calendar-grid-body.svelte | 13 + .../range-calendar-grid-head.svelte | 13 + .../range-calendar-grid-row.svelte | 13 + .../range-calendar/range-calendar-grid.svelte | 16 + .../range-calendar-head-cell.svelte | 16 + .../range-calendar-header.svelte | 16 + .../range-calendar-heading.svelte | 19 + .../range-calendar-months.svelte | 16 + .../range-calendar-next-button.svelte | 27 + .../range-calendar-prev-button.svelte | 27 + .../ui/range-calendar/range-calendar.svelte | 60 + src/lib/components/ui/resizable/index.ts | 13 + .../ui/resizable/resizable-handle.svelte | 28 + .../ui/resizable/resizable-pane-group.svelte | 22 + src/lib/components/ui/scroll-area/index.ts | 10 + .../scroll-area/scroll-area-scrollbar.svelte | 27 + .../ui/scroll-area/scroll-area.svelte | 32 + src/lib/components/ui/select/index.ts | 34 + .../ui/select/select-content.svelte | 39 + .../components/ui/select/select-item.svelte | 40 + .../components/ui/select/select-label.svelte | 16 + .../ui/select/select-separator.svelte | 11 + .../ui/select/select-trigger.svelte | 27 + src/lib/components/ui/separator/index.ts | 7 + .../components/ui/separator/separator.svelte | 22 + src/lib/components/ui/sheet/index.ts | 106 + .../components/ui/sheet/sheet-content.svelte | 47 + .../ui/sheet/sheet-description.svelte | 13 + .../components/ui/sheet/sheet-footer.svelte | 16 + .../components/ui/sheet/sheet-header.svelte | 13 + .../components/ui/sheet/sheet-overlay.svelte | 21 + .../components/ui/sheet/sheet-portal.svelte | 13 + .../components/ui/sheet/sheet-title.svelte | 16 + src/lib/components/ui/skeleton/index.ts | 7 + .../components/ui/skeleton/skeleton.svelte | 11 + src/lib/components/ui/slider/index.ts | 7 + src/lib/components/ui/slider/slider.svelte | 27 + src/lib/components/ui/sonner/index.ts | 1 + src/lib/components/ui/sonner/sonner.svelte | 20 + src/lib/components/ui/switch/index.ts | 7 + src/lib/components/ui/switch/switch.svelte | 28 + src/lib/components/ui/table/index.ts | 28 + src/lib/components/ui/table/table-body.svelte | 13 + .../components/ui/table/table-caption.svelte | 13 + src/lib/components/ui/table/table-cell.svelte | 18 + .../components/ui/table/table-footer.svelte | 13 + src/lib/components/ui/table/table-head.svelte | 19 + .../components/ui/table/table-header.svelte | 14 + src/lib/components/ui/table/table-row.svelte | 23 + src/lib/components/ui/table/table.svelte | 15 + src/lib/components/ui/tabs/index.ts | 18 + .../components/ui/tabs/tabs-content.svelte | 21 + src/lib/components/ui/tabs/tabs-list.svelte | 19 + .../components/ui/tabs/tabs-trigger.svelte | 23 + src/lib/components/ui/textarea/index.ts | 28 + .../components/ui/textarea/textarea.svelte | 38 + src/lib/components/ui/toggle-group/index.ts | 23 + .../ui/toggle-group/toggle-group-item.svelte | 31 + .../ui/toggle-group/toggle-group.svelte | 30 + src/lib/components/ui/toggle/index.ts | 31 + src/lib/components/ui/toggle/toggle.svelte | 26 + src/lib/components/ui/tooltip/index.ts | 15 + .../ui/tooltip/tooltip-content.svelte | 28 + src/lib/constants/status-codes.ts | 357 + src/lib/server/api/common/config.ts | 22 + src/lib/server/api/common/exceptions.ts | 26 + .../server/api/common/types/async-service.ts | 3 + src/lib/server/api/common/types/config.ts | 26 + src/lib/server/api/common/types/controller.ts | 11 + src/lib/server/api/common/types/email.ts | 4 + src/lib/server/api/common/types/hono.ts | 14 + src/lib/server/api/common/types/mailer.ts | 3 + src/lib/server/api/common/utils/repository.ts | 14 + src/lib/server/api/common/utils/table.ts | 30 + .../server/api/controllers/iam.controller.ts | 79 + .../migrations/0000_clear_paper_doll.sql | 50 + .../migrations/0001_gifted_james_howlett.sql | 14 + .../postgres/migrations/0002_sharp_risque.sql | 15 + .../migrations/meta/0000_snapshot.json | 247 + .../migrations/meta/0001_snapshot.json | 315 + .../migrations/meta/0002_snapshot.json | 315 + .../postgres/migrations/meta/_journal.json | 27 + .../tables/email-verifications.table.ts | 28 + .../databases/postgres/tables/files.table.ts | 12 + .../api/databases/postgres/tables/index.ts | 4 + .../postgres/tables/login-requests.table.ts | 19 + .../postgres/tables/sessions.table.ts | 22 + .../databases/postgres/tables/users.table.ts | 30 + src/lib/server/api/dtos/login.dto.ts | 7 + src/lib/server/api/dtos/update-email.dto.ts | 6 + src/lib/server/api/dtos/verify-email.dto.ts | 7 + src/lib/server/api/dtos/verify-login.dto.ts | 8 + .../api/emails/email-change-notice.email.ts | 32 + .../api/emails/login-verification.email.ts | 39 + src/lib/server/api/emails/welcome.email.ts | 34 + src/lib/server/api/index.ts | 41 + src/lib/server/api/jobs/auth-cleanup.job.ts | 44 + .../server/api/middlewares/auth.middleware.ts | 42 + .../api/middlewares/rate-limiter.middlware.ts | 34 + .../middlewares/require-auth.middleware.ts | 15 + .../email-verifications.repository.ts | 35 + .../api/repositories/files.repository.ts | 41 + .../repositories/login-requests.repository.ts | 34 + .../api/repositories/users.repository.ts | 44 + .../api/services/authentication.service.ts | 80 + .../server/api/services/drizzle.service.ts | 22 + .../services/email-verification.service.ts | 69 + .../server/api/services/hashing.service.ts | 45 + src/lib/server/api/services/iam.service.ts | 80 + src/lib/server/api/services/jobs.service.ts | 28 + src/lib/server/api/services/lucia.service.ts | 25 + src/lib/server/api/services/mailer.service.ts | 43 + src/lib/server/api/services/redis.service.ts | 16 + .../server/api/services/storage.service.ts | 44 + src/lib/server/api/services/tokens.service.ts | 35 + .../api/tests/login-requests.service.test.ts | 71 + src/lib/types.ts | 15 + src/lib/utils/api.ts | 25 + src/lib/utils/helpers.ts | 21 + src/lib/utils/superforms.ts | 20 + src/lib/utils/ui.ts | 62 + src/routes/(app)/+layout.svelte | 121 + src/routes/(app)/+page.server.ts | 15 + src/routes/(app)/+page.svelte | 6 + src/routes/(app)/settings/+layout.svelte | 31 + src/routes/(app)/settings/+page.svelte | 0 .../(app)/settings/account/+page.server.ts | 32 + .../(app)/settings/account/+page.svelte | 7 + src/routes/(app)/settings/account/schemas.ts | 9 + .../settings/account/update-email-card.svelte | 100 + src/routes/(auth)/register/+page.server.ts | 29 + src/routes/(auth)/register/+page.svelte | 87 + src/routes/(auth)/register/schemas.ts | 12 + src/routes/+layout.server.ts | 6 + src/routes/+layout.svelte | 11 + src/routes/api/[...slug]/+server.ts | 9 + static/favicon.png | Bin 0 -> 1571 bytes svelte.config.js | 19 + tailwind.config.ts | 64 + tests/test.ts | 6 + tsconfig.json | 21 + vite.config.ts | 9 + volume/cache/machine.json | 1 + volume/cache/server.test.pem | 119 + volume/cache/server.test.pem.crt | 91 + volume/cache/server.test.pem.key | 28 + .../service-catalog-3_4_1_dev-1_34_122.pickle | Bin 0 -> 4705 bytes 336 files changed, 16988 insertions(+) create mode 100644 .env.example create mode 100644 .eslintignore create mode 100644 .gitignore create mode 100644 .node-version create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/settings.json create mode 100644 Dockerfile.minio create mode 100644 README.md create mode 100644 components.json create mode 100644 docker-compose.yaml create mode 100644 drizzle.config.ts create mode 100644 eslint.config.js create mode 100644 minio-console.conf.template create mode 100644 package.json create mode 100644 playwright.config.ts create mode 100644 pnpm-lock.yaml create mode 100644 postcss.config.js create mode 100644 render.yaml create mode 100644 src/app.css create mode 100644 src/app.d.ts create mode 100644 src/app.html create mode 100644 src/hooks.server.ts create mode 100644 src/index.test.ts create mode 100644 src/lib/components/container.svelte create mode 100644 src/lib/components/pin-input.svelte 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/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-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/index.ts 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-fallback.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/button.svelte create mode 100644 src/lib/components/ui/button/index.ts 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-months.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.svelte create mode 100644 src/lib/components/ui/calendar/index.ts 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/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/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-list.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-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-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/index.ts 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/index.ts 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-title.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-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-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-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/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/index.ts 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/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-item.svelte create mode 100644 src/lib/components/ui/menubar/menubar-label.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-trigger.svelte create mode 100644 src/lib/components/ui/menubar/menubar.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-prev-button.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-content.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-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-months.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.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-item.svelte create mode 100644 src/lib/components/ui/select/select-label.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/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-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/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/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/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/constants/status-codes.ts create mode 100644 src/lib/server/api/common/config.ts create mode 100644 src/lib/server/api/common/exceptions.ts create mode 100644 src/lib/server/api/common/types/async-service.ts create mode 100644 src/lib/server/api/common/types/config.ts create mode 100644 src/lib/server/api/common/types/controller.ts create mode 100644 src/lib/server/api/common/types/email.ts create mode 100644 src/lib/server/api/common/types/hono.ts create mode 100644 src/lib/server/api/common/types/mailer.ts create mode 100644 src/lib/server/api/common/utils/repository.ts create mode 100644 src/lib/server/api/common/utils/table.ts create mode 100644 src/lib/server/api/controllers/iam.controller.ts create mode 100644 src/lib/server/api/databases/postgres/migrations/0000_clear_paper_doll.sql create mode 100644 src/lib/server/api/databases/postgres/migrations/0001_gifted_james_howlett.sql create mode 100644 src/lib/server/api/databases/postgres/migrations/0002_sharp_risque.sql create mode 100644 src/lib/server/api/databases/postgres/migrations/meta/0000_snapshot.json create mode 100644 src/lib/server/api/databases/postgres/migrations/meta/0001_snapshot.json create mode 100644 src/lib/server/api/databases/postgres/migrations/meta/0002_snapshot.json create mode 100644 src/lib/server/api/databases/postgres/migrations/meta/_journal.json create mode 100644 src/lib/server/api/databases/postgres/tables/email-verifications.table.ts create mode 100644 src/lib/server/api/databases/postgres/tables/files.table.ts create mode 100644 src/lib/server/api/databases/postgres/tables/index.ts create mode 100644 src/lib/server/api/databases/postgres/tables/login-requests.table.ts create mode 100644 src/lib/server/api/databases/postgres/tables/sessions.table.ts create mode 100644 src/lib/server/api/databases/postgres/tables/users.table.ts create mode 100644 src/lib/server/api/dtos/login.dto.ts create mode 100644 src/lib/server/api/dtos/update-email.dto.ts create mode 100644 src/lib/server/api/dtos/verify-email.dto.ts create mode 100644 src/lib/server/api/dtos/verify-login.dto.ts create mode 100644 src/lib/server/api/emails/email-change-notice.email.ts create mode 100644 src/lib/server/api/emails/login-verification.email.ts create mode 100644 src/lib/server/api/emails/welcome.email.ts create mode 100644 src/lib/server/api/index.ts create mode 100644 src/lib/server/api/jobs/auth-cleanup.job.ts create mode 100644 src/lib/server/api/middlewares/auth.middleware.ts create mode 100644 src/lib/server/api/middlewares/rate-limiter.middlware.ts create mode 100644 src/lib/server/api/middlewares/require-auth.middleware.ts create mode 100644 src/lib/server/api/repositories/email-verifications.repository.ts create mode 100644 src/lib/server/api/repositories/files.repository.ts create mode 100644 src/lib/server/api/repositories/login-requests.repository.ts create mode 100644 src/lib/server/api/repositories/users.repository.ts create mode 100644 src/lib/server/api/services/authentication.service.ts create mode 100644 src/lib/server/api/services/drizzle.service.ts create mode 100644 src/lib/server/api/services/email-verification.service.ts create mode 100644 src/lib/server/api/services/hashing.service.ts create mode 100644 src/lib/server/api/services/iam.service.ts create mode 100644 src/lib/server/api/services/jobs.service.ts create mode 100644 src/lib/server/api/services/lucia.service.ts create mode 100644 src/lib/server/api/services/mailer.service.ts create mode 100644 src/lib/server/api/services/redis.service.ts create mode 100644 src/lib/server/api/services/storage.service.ts create mode 100644 src/lib/server/api/services/tokens.service.ts create mode 100644 src/lib/server/api/tests/login-requests.service.test.ts create mode 100644 src/lib/types.ts create mode 100644 src/lib/utils/api.ts create mode 100644 src/lib/utils/helpers.ts create mode 100644 src/lib/utils/superforms.ts create mode 100644 src/lib/utils/ui.ts create mode 100644 src/routes/(app)/+layout.svelte create mode 100644 src/routes/(app)/+page.server.ts create mode 100644 src/routes/(app)/+page.svelte create mode 100644 src/routes/(app)/settings/+layout.svelte create mode 100644 src/routes/(app)/settings/+page.svelte create mode 100644 src/routes/(app)/settings/account/+page.server.ts create mode 100644 src/routes/(app)/settings/account/+page.svelte create mode 100644 src/routes/(app)/settings/account/schemas.ts create mode 100644 src/routes/(app)/settings/account/update-email-card.svelte create mode 100644 src/routes/(auth)/register/+page.server.ts create mode 100644 src/routes/(auth)/register/+page.svelte create mode 100644 src/routes/(auth)/register/schemas.ts create mode 100644 src/routes/+layout.server.ts create mode 100644 src/routes/+layout.svelte create mode 100644 src/routes/api/[...slug]/+server.ts create mode 100644 static/favicon.png create mode 100644 svelte.config.js create mode 100644 tailwind.config.ts create mode 100644 tests/test.ts create mode 100644 tsconfig.json create mode 100644 vite.config.ts create mode 100644 volume/cache/machine.json create mode 100644 volume/cache/server.test.pem create mode 100644 volume/cache/server.test.pem.crt create mode 100644 volume/cache/server.test.pem.key create mode 100644 volume/cache/service-catalog-3_4_1_dev-1_34_122.pickle diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c2fdb5f --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +# API +ORIGIN=http://localhost:5173 + +# Database +DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres + +# Redis +REDIS_URL=redis://localhost:6379 + +# Storage +PUBLIC_IMAGE_URI=http://localhost:9000/dev +STORAGE_BUCKET=dev +STORAGE_URL=http://localhost:9000 +STORAGE_ACCESS_KEY=user +STORAGE_SECRET_KEY=password diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..3897265 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,13 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6635cf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..7d1aef0 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +22.1.0 \ No newline at end of file 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..cc41cea --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..8bc6e86 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "useTabs": true, + "singleQuote": true, + "trailingComma": "none", + "printWidth": 100, + "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], + "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e76b3ee --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "vitest.disableWorkspaceWarning": true +} \ No newline at end of file diff --git a/Dockerfile.minio b/Dockerfile.minio new file mode 100644 index 0000000..78a36b0 --- /dev/null +++ b/Dockerfile.minio @@ -0,0 +1,3 @@ +FROM nginx:stable-alpine-slim +COPY minio-console.conf.template /etc/nginx/templates/ +RUN rm /etc/nginx/conf.d/default.conf /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..274d0fd --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# Sveltekit - Taro Stack + +## ❗ Important + +If you forked this repository before May 27th, you'll want to view commit `653e2c2`. There was an issue with the Hono context not correctly parsing routes. + +## ❔ What + +A scalable, testable, extensible, template for Sveltekit. + +Sveltekit is awesome, but sometimes you need a bit more capability in the backend than what frameworks like +NextJS & Sveltekit can deliver. + +To remedy this, I've attatched a fully fletched backend to run on the Sveltekit process and forward all API requests to it and paired it with some architectural patterns. + +`/api/[...slugs]` + +```ts +import app from '$lib/api'; +import type { RequestHandler } from '@sveltejs/kit'; + +export const GET: RequestHandler = ({ request }) => app.fetch(request); +export const PUT: RequestHandler = ({ request }) => app.fetch(request); +export const DELETE: RequestHandler = ({ request }) => app.fetch(request); +export const POST: RequestHandler = ({ request }) => app.fetch(request); +``` + +## Local Setup + +1. Make sure Docker is running +2. Copy the `.env.example` file and rename to `.env` +3. `pnpm install` +4. `pnpm initialize`(this will start the docker-compose and run the initial database migration.) +5. `pnpm dev` + +No additional setup is required, zero api keys, zero services to signup for, zero cost. + +## How to Use + +This is **not** supposed to serve as an all batteries included ["production boilerplate"](https://github.com/ixartz/Next-js-Boilerplate) with 200 useless sponsored features that get in your way. Templates that do this are ANYTHING but "production" and "quick start". + +This is stack is designed to be library agnostic. The philosophy here is to boostrap the concrete, repetitive, and time consuming tasks that every application will need reguardless of what you're building. + +**So - fork this repo, add your favorite libraries, and build out your own "more opinionated" personal template tailored to you**! + +## Features + +- 🟢 Full E2E typesafety +- 🟢 RPC Client for API Requests +- 🟢 Custom Fetch Wrapper +- 🟢 Deployment Template +- 🟠 Authentication + - 🟢 Email/Passkey + - 🔴 OAuth + - 🟢 Email Update/Verifiaction + - 🟢 Rate limiter + +## Technologies + +I'm mostly unopinionated or what technology or libaries someone uses. Wanna [uwu'ify](https://www.npmjs.com/package/owoifyx) your entire fucking app? Go for it. + +That being said, there are some libaries that embody my philosophies of building software more than others, + +- [Lucia](https://lucia-auth.com): Hits the right level of abstraction for me. Hand me the tools to build a secure authentication system and let me implement it to suite my needs +- [Drizzle](https://orm.drizzle.team/) - Drizzle advertises itself as an ORM but I think its deceptive. Its a query builder with a migration client. Everytime I've used an ORM, I find myself fighting it for sometimes the simplist of use cases. Drizzle just gives you type-safety while querying SQL in a native fashion. Learn SQL, not ORMs. +- [Hono](https://hono.dev/): Fast, lightweight, and built on **web standards**; meaning it can run anywhere you're Sveltekit app can. It's essentially a better, newer, and ironically more stable Express.JS. This provides us an extreemely good foundation to cleanly build ontop of without having to teardown first. It has a zod adapter for validating DTO's which can be shared with the frontend too. +- [Sveltekit](https://kit.svelte.dev/): After trying Vue, React, Next, and pretty much every frontend framework in the JS ecosystem, its safe to say I vastly prefer Svelte and its priority of building on **web standards**. + +## Architecture + +There are a few popular architectures for structuring backends. Technical, Onion, DDD, VSA, and the list goes on. I almost always choose +to start with Technical and let the project naturally evolve into one of the others as complexity grows. + +### Backend Folder Structure + +- **controllers** - Responsible for routing requests + +- **services** - Responsible for handling business logic. + +- **repositories** - Responsible for retrieving and + storing data. + +- **infrastructure** - Handles the implementation of external services or backend operations. + +- **middleware** - Middlware our request router is responsible for handling. + +- **providers** - Injectable services + +- **dtos** - Data Transfer Objects (DTOs) are used to define the shape of data that is passed. + +- **common** - Anything commonly shared throughout the backend + +### File Naming + +You might notice how each file in the backend is postfixed with its architectural type(e.g. `iam.service.ts`). This allows +us to easily reorganize the folder structure to suite a different architecture pattern if the domain becomes more complex. + +For example, if you want to group folders by domain(DDD), you simply drag and drop all related files to that folder. + +``` +└── events/ + ├── events.controller.ts + ├── events.service.ts + └── events.repository.ts +``` + +## Testing + +Testing probably isn't first and foremost when creating an app. Thats fine. You should not be spending time writing tests if your app is mutable. + +BUT, a good stack should be **testable** when the time to solidify a codebase arrives. I created this stack with that pinciple in mind. I've provided a examples of how to write these tests under `authentication.service.test.ts` or `users.service.test.ts` diff --git a/components.json b/components.json new file mode 100644 index 0000000..825eff7 --- /dev/null +++ b/components.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "style": "default", + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app.css", + "baseColor": "slate" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils/ui" + }, + "typescript": true +} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..03f131d --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,58 @@ +version: '3.8' +services: + postgres: + image: postgres:latest + container_name: tofu_postgres + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - '5432:5432' + volumes: + - postgres_data:/data + redis: + image: redis:latest + container_name: tofu_redis + ports: + - '6379:6379' + volumes: + - redis_data:/data + minio: + image: docker.io/bitnami/minio + container_name: tofu_minio + ports: + - '9000:9000' + - '9001:9001' + networks: + - minionetwork + volumes: + - 'minio_data:/data' + environment: + - MINIO_ROOT_USER=user + - MINIO_ROOT_PASSWORD=password + - MINIO_DEFAULT_BUCKETS=dev + mailpit: + image: axllent/mailpit + container_name: tofu_mailpit + volumes: + - mailpit_data:/data + ports: + - 8025:8025 + - 1025:1025 + environment: + MP_MAX_MESSAGES: 5000 + MP_DATABASE: /data/mailpit.db + MP_SMTP_AUTH_ACCEPT_ANY: 1 + MP_SMTP_AUTH_ALLOW_INSECURE: 1 + +volumes: + postgres_data: + redis_data: + mailpit_data: + minio_data: + driver: local + +networks: + minionetwork: + driver: bridge \ No newline at end of file diff --git a/drizzle.config.ts b/drizzle.config.ts new file mode 100644 index 0000000..5ec2892 --- /dev/null +++ b/drizzle.config.ts @@ -0,0 +1,16 @@ +import type { Config } from 'drizzle-kit'; + +export default { + out: './src/lib/server/api/databases/postgres/migrations', + schema: './src/lib/server/api/databases/postgres/tables/*.table.ts', + breakpoints: false, + strict: true, + dialect: 'postgresql', + dbCredentials: { + url: process.env.DATABASE_URL! + }, + migrations: { + table: 'migrations', + schema: 'public' + } +} satisfies Config; diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..a351fa9 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,33 @@ +import js from '@eslint/js'; +import ts from 'typescript-eslint'; +import svelte from 'eslint-plugin-svelte'; +import prettier from 'eslint-config-prettier'; +import globals from 'globals'; + +/** @type {import('eslint').Linter.FlatConfig[]} */ +export default [ + js.configs.recommended, + ...ts.configs.recommended, + ...svelte.configs['flat/recommended'], + prettier, + ...svelte.configs['flat/prettier'], + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + } + }, + { + files: ['**/*.svelte'], + languageOptions: { + parserOptions: { + parser: ts.parser + } + } + }, + { + ignores: ['build/', '.svelte-kit/', 'dist/'] + } +]; diff --git a/minio-console.conf.template b/minio-console.conf.template new file mode 100644 index 0000000..34d022f --- /dev/null +++ b/minio-console.conf.template @@ -0,0 +1,41 @@ +upstream minio_console { + server ${MINIO_HOST}:${MINIO_CONSOLE_PORT}; +} + +server { + listen ${PORT}; + + # Allow special characters in headers + ignore_invalid_headers off; + # Allow any size file to be uploaded. + # Set to a value such as 1000m; to restrict file size to a specific value + client_max_body_size 0; + # Disable buffering + proxy_buffering off; + proxy_request_buffering off; + + location / { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-NginX-Proxy true; + + # This is necessary to pass the correct IP to be hashed + real_ip_header X-Real-IP; + + proxy_connect_timeout 300; + + # To support websockets in MinIO versions released after January 2023 + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress) + # Uncomment the following line to set the Origin request to an empty string + # proxy_set_header Origin ''; + + chunked_transfer_encoding off; + + proxy_pass http://minio_console; # This uses the upstream directive definition to load balance + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..9c8dcd9 --- /dev/null +++ b/package.json @@ -0,0 +1,90 @@ +{ + "name": "taro-stack", + "version": "0.0.1", + "private": true, + "scripts": { + "db:push": "drizzle-kit push", + "db:generate": "drizzle-kit generate", + "db:migrate": "drizzle-kit migrate", + "db:studio": "drizzle-kit studio --verbose", + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "test": "npm run test:integration && npm run test:unit", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "initialize": "pnpm install && docker-compose up --no-recreate -d && pnpm db:migrate", + "lint": "prettier --check . && eslint .", + "format": "prettier --write .", + "test:integration": "playwright test", + "test:unit": "vitest" + }, + "devDependencies": { + "@aws-sdk/client-s3": "^3.651.0", + "@hono/zod-validator": "^0.2.2", + "@lucia-auth/adapter-drizzle": "^1.1.0", + "@paralleldrive/cuid2": "^2.2.2", + "@playwright/test": "^1.47.0", + "@sveltejs/adapter-node": "^5.2.2", + "@sveltejs/kit": "^2.5.26", + "@sveltejs/vite-plugin-svelte": "^4.0.0-next.7", + "@tailwindcss/typography": "^0.5.15", + "@types/eslint": "^9.6.1", + "@types/node": "^22.5.4", + "@typescript-eslint/eslint-plugin": "^8.5.0", + "@typescript-eslint/parser": "^8.5.0", + "arctic": "^1.9.2", + "autoprefixer": "^10.4.20", + "bullmq": "^5.13.0", + "chalk": "^5.3.0", + "dotenv-cli": "^7.4.2", + "drizzle-kit": "^0.26.2", + "drizzle-orm": "^0.35.1", + "eslint": "^9.10.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-svelte": "^2.43.0", + "hono": "^4.6.1", + "ioredis": "^5.4.1", + "lucia": "^3.2.0", + "lucide-svelte": "^0.441.0", + "oslo": "^1.2.1", + "pg": "^8.12.0", + "postcss": "^8.4.45", + "postgres": "^3.4.4", + "prettier": "^3.3.3", + "prettier-plugin-svelte": "^3.2.6", + "prettier-plugin-tailwindcss": "^0.6.6", + "reflect-metadata": "^0.2.2", + "svelte": "5.0.0-next.164", + "svelte-check": "^4.0.2", + "svelte-dnd-action": "^0.9.50", + "svelte-eslint-parser": "^0.41.0", + "sveltekit-search-params": "^3.0.0", + "sveltekit-superforms": "^2.17.0", + "tailwindcss": "^3.4.11", + "tsyringe": "^4.8.0", + "typescript": "^5.6.2", + "vite": "^5.4.4", + "vitest": "^2.1.0", + "zod": "^3.23.8" + }, + "type": "module", + "dependencies": { + "@internationalized/date": "^3.5.5", + "bits-ui": "^0.21.13", + "clsx": "^2.1.1", + "cmdk-sv": "^0.0.18", + "embla-carousel-svelte": "^8.2.1", + "formsnap": "^1.0.1", + "hono-rate-limiter": "^0.4.0", + "mode-watcher": "^0.4.1", + "paneforge": "^0.0.5", + "rate-limit-redis": "^4.2.0", + "redis": "^4.7.0", + "redis-om": "^0.4.6", + "svelte-sonner": "^0.3.28", + "tailwind-merge": "^2.5.2", + "tailwind-variants": "^0.2.1", + "vaul-svelte": "^0.3.2" + } +} diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..1c5d7a1 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,12 @@ +import type { PlaywrightTestConfig } from '@playwright/test'; + +const config: PlaywrightTestConfig = { + webServer: { + command: 'npm run build && npm run preview', + port: 4173 + }, + testDir: 'tests', + testMatch: /(.+\.)?(test|spec)\.[jt]s/ +}; + +export default config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..11a749a --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,7388 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@internationalized/date': + specifier: ^3.5.5 + version: 3.5.5 + bits-ui: + specifier: ^0.21.13 + version: 0.21.13(svelte@5.0.0-next.164) + clsx: + specifier: ^2.1.1 + version: 2.1.1 + cmdk-sv: + specifier: ^0.0.18 + version: 0.0.18(svelte@5.0.0-next.164) + embla-carousel-svelte: + specifier: ^8.2.1 + version: 8.2.1(svelte@5.0.0-next.164) + formsnap: + specifier: ^1.0.1 + version: 1.0.1(svelte@5.0.0-next.164)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)) + hono-rate-limiter: + specifier: ^0.4.0 + version: 0.4.0(hono@4.6.1) + mode-watcher: + specifier: ^0.4.1 + version: 0.4.1(svelte@5.0.0-next.164) + paneforge: + specifier: ^0.0.5 + version: 0.0.5(svelte@5.0.0-next.164) + rate-limit-redis: + specifier: ^4.2.0 + version: 4.2.0(express-rate-limit@7.4.0(express@4.21.0)) + redis: + specifier: ^4.7.0 + version: 4.7.0 + redis-om: + specifier: ^0.4.6 + version: 0.4.6 + svelte-sonner: + specifier: ^0.3.28 + version: 0.3.28(svelte@5.0.0-next.164) + tailwind-merge: + specifier: ^2.5.2 + version: 2.5.2 + tailwind-variants: + specifier: ^0.2.1 + version: 0.2.1(tailwindcss@3.4.11) + vaul-svelte: + specifier: ^0.3.2 + version: 0.3.2(svelte@5.0.0-next.164) + devDependencies: + '@aws-sdk/client-s3': + specifier: ^3.651.0 + version: 3.651.0 + '@hono/zod-validator': + specifier: ^0.2.2 + version: 0.2.2(hono@4.6.1)(zod@3.23.8) + '@lucia-auth/adapter-drizzle': + specifier: ^1.1.0 + version: 1.1.0(drizzle-orm@0.35.1(pg@8.12.0)(postgres@3.4.4)(react@18.3.1))(lucia@3.2.0) + '@paralleldrive/cuid2': + specifier: ^2.2.2 + version: 2.2.2 + '@playwright/test': + specifier: ^1.47.0 + version: 1.47.0 + '@sveltejs/adapter-node': + specifier: ^5.2.2 + version: 5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4))) + '@sveltejs/kit': + specifier: ^2.5.26 + version: 2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + '@sveltejs/vite-plugin-svelte': + specifier: ^4.0.0-next.7 + version: 4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + '@tailwindcss/typography': + specifier: ^0.5.15 + version: 0.5.15(tailwindcss@3.4.11) + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + '@types/node': + specifier: ^22.5.4 + version: 22.5.4 + '@typescript-eslint/eslint-plugin': + specifier: ^8.5.0 + version: 8.5.0(@typescript-eslint/parser@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/parser': + specifier: ^8.5.0 + version: 8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) + arctic: + specifier: ^1.9.2 + version: 1.9.2 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.45) + bullmq: + specifier: ^5.13.0 + version: 5.13.0 + chalk: + specifier: ^5.3.0 + version: 5.3.0 + dotenv-cli: + specifier: ^7.4.2 + version: 7.4.2 + drizzle-kit: + specifier: ^0.26.2 + version: 0.26.2 + drizzle-orm: + specifier: ^0.35.1 + version: 0.35.1(pg@8.12.0)(postgres@3.4.4)(react@18.3.1) + eslint: + specifier: ^9.10.0 + version: 9.10.0(jiti@1.21.6) + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@9.10.0(jiti@1.21.6)) + eslint-plugin-svelte: + specifier: ^2.43.0 + version: 2.43.0(eslint@9.10.0(jiti@1.21.6))(svelte@5.0.0-next.164) + hono: + specifier: ^4.6.1 + version: 4.6.1 + ioredis: + specifier: ^5.4.1 + version: 5.4.1 + lucia: + specifier: ^3.2.0 + version: 3.2.0 + lucide-svelte: + specifier: ^0.441.0 + version: 0.441.0(svelte@5.0.0-next.164) + oslo: + specifier: ^1.2.1 + version: 1.2.1 + pg: + specifier: ^8.12.0 + version: 8.12.0 + postcss: + specifier: ^8.4.45 + version: 8.4.45 + postgres: + specifier: ^3.4.4 + version: 3.4.4 + prettier: + specifier: ^3.3.3 + version: 3.3.3 + prettier-plugin-svelte: + specifier: ^3.2.6 + version: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.164) + prettier-plugin-tailwindcss: + specifier: ^0.6.6 + version: 0.6.6(prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@5.0.0-next.164))(prettier@3.3.3) + reflect-metadata: + specifier: ^0.2.2 + version: 0.2.2 + svelte: + specifier: 5.0.0-next.164 + version: 5.0.0-next.164 + svelte-check: + specifier: ^4.0.2 + version: 4.0.2(svelte@5.0.0-next.164)(typescript@5.6.2) + svelte-dnd-action: + specifier: ^0.9.50 + version: 0.9.50(svelte@5.0.0-next.164) + svelte-eslint-parser: + specifier: ^0.41.0 + version: 0.41.0(svelte@5.0.0-next.164) + sveltekit-search-params: + specifier: ^3.0.0 + version: 3.0.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + sveltekit-superforms: + specifier: ^2.17.0 + version: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164) + tailwindcss: + specifier: ^3.4.11 + version: 3.4.11 + tsyringe: + specifier: ^4.8.0 + version: 4.8.0 + typescript: + specifier: ^5.6.2 + version: 5.6.2 + vite: + specifier: ^5.4.4 + version: 5.4.4(@types/node@22.5.4) + vitest: + specifier: ^2.1.0 + version: 2.1.0(@types/node@22.5.4) + zod: + specifier: ^3.23.8 + version: 3.23.8 + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@ark/schema@0.2.0': + resolution: {integrity: sha512-IkNWCSHdjaoemMXpps4uFHEAQzwJPbTAS8K2vcQpk90sa+eNBuPSVyB/81/Qyl1VYW0iX3ceGC5NL/OznQv1jg==} + + '@ark/util@0.1.0': + resolution: {integrity: sha512-qCLYICQoCy3kEKDVwirQp8qvxhY7NJd8BhhoHaj1l3wCFAk9NUbcDsxAkPStZEMdPI/d7NcbGJe8SWZuRG2twQ==} + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-s3@3.651.0': + resolution: {integrity: sha512-37+kxxjnlOAUCb1aHpoLakW4XRG23HrkX8X3cEjxaFLQxorPUiMvfAYQEQQkYD5yggaG+5aM5GAhxkTUTqA5xw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sso-oidc@3.650.0': + resolution: {integrity: sha512-6J7IS0f8ovhvbIAZaynOYP+jPX8344UlTjwHxjaXHgFvI8axu3+NslKtEEV5oHLhgzDvrKbinsu5lgE2n4Sqng==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.650.0 + + '@aws-sdk/client-sso@3.650.0': + resolution: {integrity: sha512-YKm14gCMChD/jlCisFlsVqB8HJujR41bl4Fup2crHwNJxhD/9LTnzwMiVVlBqlXr41Sfa6fSxczX2AMP8NM14A==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/client-sts@3.650.0': + resolution: {integrity: sha512-ISK0ZQYA7O5/WYgslpWy956lUBudGC9d7eL0FFbiL0j50N80Gx3RUv22ezvZgxJWE0W3DqNr4CE19sPYn4Lw8g==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/core@3.649.0': + resolution: {integrity: sha512-dheG/X2y25RHE7K+TlS32kcy7TgDg1OpWV44BQRoE0OBPAWmFR1D1qjjTZ7WWrdqRPKzcnDj1qED8ncyncOX8g==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-env@3.649.0': + resolution: {integrity: sha512-tViwzM1dauksA3fdRjsg0T8mcHklDa8EfveyiQKK6pUJopkqV6FQx+X5QNda0t/LrdEVlFZvwHNdXqOEfc83TA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-http@3.649.0': + resolution: {integrity: sha512-ODAJ+AJJq6ozbns6ejGbicpsQ0dyMOpnGlg0J9J0jITQ05DKQZ581hdB8APDOZ9N8FstShP6dLZflSj8jb5fNA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-ini@3.650.0': + resolution: {integrity: sha512-x2M9buZxIsKuUbuDgkGHhAKYBpn0/rYdKlwuFuOhXyyAcnhvPj0lgNF2KE4ld/GF1mKr7FF/uV3G9lM6PFaYmA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.650.0 + + '@aws-sdk/credential-provider-node@3.650.0': + resolution: {integrity: sha512-uBra5YjzS/gWSekAogfqJfY6c+oKQkkou7Cjc4d/cpMNvQtF1IBdekJ7NaE1RfsDEz3uH1+Myd07YWZAJo/2Qw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-process@3.649.0': + resolution: {integrity: sha512-6VYPQpEVpU+6DDS/gLoI40ppuNM5RPIEprK30qZZxnhTr5wyrGOeJ7J7wbbwPOZ5dKwta290BiJDU2ipV8Y9BQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-sso@3.650.0': + resolution: {integrity: sha512-069nkhcwximbvyGiAC6Fr2G+yrG/p1S3NQ5BZ2cMzB1hgUKo6TvgFK7nriYI4ljMQ+UWxqPwIdTqiUmn2iJmhg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.649.0': + resolution: {integrity: sha512-XVk3WsDa0g3kQFPmnCH/LaCtGY/0R2NDv7gscYZSXiBZcG/fixasglTprgWSp8zcA0t7tEIGu9suyjz8ZwhymQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.649.0 + + '@aws-sdk/middleware-bucket-endpoint@3.649.0': + resolution: {integrity: sha512-ZdDICtUU4YZkrVllTUOH1Fj/F3WShLhkfNKJE3HJ/yj6pS8JS9P2lWzHiHkHiidjrHSxc6NuBo6vuZ+182XLbw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-expect-continue@3.649.0': + resolution: {integrity: sha512-pW2id/mWNd+L0/hZKp5yL3J+8rTwsamu9E69Hc5pM3qTF4K4DTZZ+A0sQbY6duIvZvc8IbQHbSMulBOLyWNP3A==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-flexible-checksums@3.651.0': + resolution: {integrity: sha512-mGAOIjhNDcBK5+JD+W+Ky5YJL98jTNFTENJV/GiQ9t3CdqK3p02MNr/T6VwzEpzsJvJD23amogiEZeiqSQiibg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-host-header@3.649.0': + resolution: {integrity: sha512-PjAe2FocbicHVgNNwdSZ05upxIO7AgTPFtQLpnIAmoyzMcgv/zNB5fBn3uAnQSAeEPPCD+4SYVEUD1hw1ZBvEg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-location-constraint@3.649.0': + resolution: {integrity: sha512-O9AXhaFUQx34UTnp/cKCcaWW/IVk4mntlWfFjsIxvRatamKaY33b5fOiakGG+J1t0QFK0niDBSvOYUR1fdlHzw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-logger@3.649.0': + resolution: {integrity: sha512-qdqRx6q7lYC6KL/NT9x3ShTL0TBuxdkCczGzHzY3AnOoYUjnCDH7Vlq867O6MAvb4EnGNECFzIgtkZkQ4FhY5w==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.649.0': + resolution: {integrity: sha512-IPnO4wlmaLRf6IYmJW2i8gJ2+UPXX0hDRv1it7Qf8DpBW+lGyF2rnoN7NrFX0WIxdGOlJF1RcOr/HjXb2QeXfQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.649.0': + resolution: {integrity: sha512-3H8735xTAD7IxNdreT6qv2YRk4CGOGfz8ufZo5pROJYZ4N5rfcdDMvb8szMSLvQHegqS4v1DqO9nrOPgc0I2Qg==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-ssec@3.649.0': + resolution: {integrity: sha512-r/WBIpX+Kcx+AV5vJ+LbdDOuibk7spBqcFK2LytQjOZKPksZNRAM99khbFe9vr9S1+uDmCLVjAVkIfQ5seJrOw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/middleware-user-agent@3.649.0': + resolution: {integrity: sha512-q6sO10dnCXoxe9thobMJxekhJumzd1j6dxcE1+qJdYKHJr6yYgWbogJqrLCpWd30w0lEvnuAHK8lN2kWLdJxJw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/region-config-resolver@3.649.0': + resolution: {integrity: sha512-xURBvdQXvRvca5Du8IlC5FyCj3pkw8Z75+373J3Wb+vyg8GjD14HfKk1Je1HCCQDyIE9VB/scYDcm9ri0ppePw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.649.0': + resolution: {integrity: sha512-feJfSHtCarFmTMZSE5k7/A+m4FrdCrmotljc/AmXArWy3wl8XFyxE5tFVW/PiUgbgeoVDN+ZLt3YYtItHfNUWQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/token-providers@3.649.0': + resolution: {integrity: sha512-ZBqr+JuXI9RiN+4DSZykMx5gxpL8Dr3exIfFhxMiwAP3DQojwl0ub8ONjMuAjq9OvmX6n+jHZL6fBnNgnNFC8w==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sso-oidc': ^3.649.0 + + '@aws-sdk/types@3.649.0': + resolution: {integrity: sha512-PuPw8RysbhJNlaD2d/PzOTf8sbf4Dsn2b7hwyGh7YVG3S75yTpxSAZxrnhKsz9fStgqFmnw/jUfV/G+uQAeTVw==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-arn-parser@3.568.0': + resolution: {integrity: sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-endpoints@3.649.0': + resolution: {integrity: sha512-bZI1Wc3R/KibdDVWFxX/N4AoJFG4VJ92Dp4WYmOrVD6VPkb8jPz7ZeiYc7YwPl8NoDjYyPneBV0lEoK/V8OKAA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-locate-window@3.568.0': + resolution: {integrity: sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-user-agent-browser@3.649.0': + resolution: {integrity: sha512-IY43r256LhKAvdEVQO/FPdUyVpcZS5EVxh/WHVdNzuN1bNLoUK2rIzuZqVA0EGguvCxoXVmQv9m50GvG7cGktg==} + + '@aws-sdk/util-user-agent-node@3.649.0': + resolution: {integrity: sha512-x5DiLpZDG/AJmCIBnE3Xhpwy35QIo3WqNiOpw6ExVs1NydbM/e90zFPSfhME0FM66D/WorigvluBxxwjxDm/GA==} + engines: {node: '>=16.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.649.0': + resolution: {integrity: sha512-XVESKkK7m5LdCVzZ3NvAja40BEyCrfPqtaiFAAhJIvW2U1Edyugf2o3XikuQY62crGT6BZagxJFgOiLKvuTiTg==} + engines: {node: '>=16.0.0'} + + '@babel/runtime@7.25.6': + resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} + engines: {node: '>=6.9.0'} + + '@drizzle-team/brocli@0.10.1': + resolution: {integrity: sha512-AHy0vjc+n/4w/8Mif+w86qpppHuF3AyXbcWW+R/W7GNA3F5/p2nuhlkCJaTXSLZheB4l1rtHzOfr9A7NwoR/Zg==} + + '@emnapi/core@0.45.0': + resolution: {integrity: sha512-DPWjcUDQkCeEM4VnljEOEcXdAD7pp8zSZsgOujk/LGIwCXWbXJngin+MO4zbH429lzeC3WbYLGjE2MaUOwzpyw==} + + '@emnapi/runtime@0.45.0': + resolution: {integrity: sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==} + + '@esbuild-kit/core-utils@3.3.2': + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild-kit/esm-loader@2.6.5': + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild/aix-ppc64@0.19.12': + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.18.20': + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.19.12': + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.18.20': + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.19.12': + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.18.20': + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.19.12': + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.18.20': + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.19.12': + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.18.20': + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.19.12': + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.18.20': + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.19.12': + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.18.20': + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.19.12': + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.18.20': + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.19.12': + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.18.20': + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.19.12': + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.18.20': + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.19.12': + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.18.20': + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.19.12': + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.18.20': + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.19.12': + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.18.20': + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.19.12': + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.18.20': + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.19.12': + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.18.20': + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.19.12': + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.18.20': + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.19.12': + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.18.20': + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.19.12': + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.18.20': + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.19.12': + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.18.20': + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.19.12': + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.18.20': + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.19.12': + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.18.20': + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.19.12': + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.18.20': + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.19.12': + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.18.0': + resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.10.0': + resolution: {integrity: sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.1.0': + resolution: {integrity: sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@exodus/schemasafe@1.3.0': + resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} + + '@floating-ui/core@1.6.7': + resolution: {integrity: sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==} + + '@floating-ui/dom@1.6.10': + resolution: {integrity: sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==} + + '@floating-ui/utils@0.2.7': + resolution: {integrity: sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==} + + '@gcornut/valibot-json-schema@0.31.0': + resolution: {integrity: sha512-3xGptCurm23e7nuPQkdrE5rEs1FeTPHhAUsBuwwqG4/YeZLwJOoYZv+fmsppUEfo5y9lzUwNQrNqLS/q7HMc7g==} + hasBin: true + + '@hapi/hoek@9.3.0': + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + + '@hapi/topo@5.1.0': + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + + '@hono/zod-validator@0.2.2': + resolution: {integrity: sha512-dSDxaPV70Py8wuIU2QNpoVEIOSzSXZ/6/B/h4xA7eOMz7+AarKTSGV8E6QwrdcCbBLkpqfJ4Q2TmBO0eP1tCBQ==} + peerDependencies: + hono: '>=3.9.0' + zod: ^3.19.1 + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} + + '@internationalized/date@3.5.5': + resolution: {integrity: sha512-H+CfYvOZ0LTJeeLOqm19E3uj/4YjrmOFtBufDHPfvtI80hFAMqtrp7oCACpe4Cil5l8S0Qu/9dYfZc/5lY8WQQ==} + + '@ioredis/commands@1.2.0': + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@lucia-auth/adapter-drizzle@1.1.0': + resolution: {integrity: sha512-iCTnZWvfI5lLZOdUHZYiXA1jaspIFEeo2extLxQ3DjP3uOVys7IPwBi7zezLIRu9dhro4H4Kji+7gSYyjcef2A==} + peerDependencies: + drizzle-orm: '>= 0.29 <1' + lucia: 3.x + + '@melt-ui/svelte@0.76.2': + resolution: {integrity: sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==} + peerDependencies: + svelte: '>=3 <5' + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + cpu: [arm64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + cpu: [x64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + cpu: [arm64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + cpu: [arm] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + cpu: [x64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + cpu: [x64] + os: [win32] + + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + + '@node-rs/argon2-android-arm-eabi@1.7.0': + resolution: {integrity: sha512-udDqkr5P9E+wYX1SZwAVPdyfYvaF4ry9Tm+R9LkfSHbzWH0uhU6zjIwNRp7m+n4gx691rk+lqqDAIP8RLKwbhg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@node-rs/argon2-android-arm64@1.7.0': + resolution: {integrity: sha512-s9j/G30xKUx8WU50WIhF0fIl1EdhBGq0RQ06lEhZ0Gi0ap8lhqbE2Bn5h3/G2D1k0Dx+yjeVVNmt/xOQIRG38A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@node-rs/argon2-darwin-arm64@1.7.0': + resolution: {integrity: sha512-ZIz4L6HGOB9U1kW23g+m7anGNuTZ0RuTw0vNp3o+2DWpb8u8rODq6A8tH4JRL79S+Co/Nq608m9uackN2pe0Rw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@node-rs/argon2-darwin-x64@1.7.0': + resolution: {integrity: sha512-5oi/pxqVhODW/pj1+3zElMTn/YukQeywPHHYDbcAW3KsojFjKySfhcJMd1DjKTc+CHQI+4lOxZzSUzK7mI14Hw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@node-rs/argon2-freebsd-x64@1.7.0': + resolution: {integrity: sha512-Ify08683hA4QVXYoIm5SUWOY5DPIT/CMB0CQT+IdxQAg/F+qp342+lUkeAtD5bvStQuCx/dFO3bnnzoe2clMhA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@node-rs/argon2-linux-arm-gnueabihf@1.7.0': + resolution: {integrity: sha512-7DjDZ1h5AUHAtRNjD19RnQatbhL+uuxBASuuXIBu4/w6Dx8n7YPxwTP4MXfsvuRgKuMWiOb/Ub/HJ3kXVCXRkg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@node-rs/argon2-linux-arm64-gnu@1.7.0': + resolution: {integrity: sha512-nJDoMP4Y3YcqGswE4DvP080w6O24RmnFEDnL0emdI8Nou17kNYBzP2546Nasx9GCyLzRcYQwZOUjrtUuQ+od2g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@node-rs/argon2-linux-arm64-musl@1.7.0': + resolution: {integrity: sha512-BKWS8iVconhE3jrb9mj6t1J9vwUqQPpzCbUKxfTGJfc+kNL58F1SXHBoe2cDYGnHrFEHTY0YochzXoAfm4Dm/A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@node-rs/argon2-linux-x64-gnu@1.7.0': + resolution: {integrity: sha512-EmgqZOlf4Jurk/szW1iTsVISx25bKksVC5uttJDUloTgsAgIGReCpUUO1R24pBhu9ESJa47iv8NSf3yAfGv6jQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@node-rs/argon2-linux-x64-musl@1.7.0': + resolution: {integrity: sha512-/o1efYCYIxjfuoRYyBTi2Iy+1iFfhqHCvvVsnjNSgO1xWiWrX0Rrt/xXW5Zsl7vS2Y+yu8PL8KFWRzZhaVxfKA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@node-rs/argon2-wasm32-wasi@1.7.0': + resolution: {integrity: sha512-Evmk9VcxqnuwQftfAfYEr6YZYSPLzmKUsbFIMep5nTt9PT4XYRFAERj7wNYp+rOcBenF3X4xoB+LhwcOMTNE5w==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@node-rs/argon2-win32-arm64-msvc@1.7.0': + resolution: {integrity: sha512-qgsU7T004COWWpSA0tppDqDxbPLgg8FaU09krIJ7FBl71Sz8SFO40h7fDIjfbTT5w7u6mcaINMQ5bSHu75PCaA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@node-rs/argon2-win32-ia32-msvc@1.7.0': + resolution: {integrity: sha512-JGafwWYQ/HpZ3XSwP4adQ6W41pRvhcdXvpzIWtKvX+17+xEXAe2nmGWM6s27pVkg1iV2ZtoYLRDkOUoGqZkCcg==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@node-rs/argon2-win32-x64-msvc@1.7.0': + resolution: {integrity: sha512-9oq4ShyFakw8AG3mRls0AoCpxBFcimYx7+jvXeAf2OqKNO+mSA6eZ9z7KQeVCi0+SOEUYxMGf5UiGiDb9R6+9Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@node-rs/argon2@1.7.0': + resolution: {integrity: sha512-zfULc+/tmcWcxn+nHkbyY8vP3+MpEqKORbszt4UkpqZgBgDAAIYvuDN/zukfTgdmo6tmJKKVfzigZOPk4LlIog==} + engines: {node: '>= 10'} + + '@node-rs/bcrypt-android-arm-eabi@1.9.0': + resolution: {integrity: sha512-nOCFISGtnodGHNiLrG0WYLWr81qQzZKYfmwHc7muUeq+KY0sQXyHOwZk9OuNQAWv/lnntmtbwkwT0QNEmOyLvA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@node-rs/bcrypt-android-arm64@1.9.0': + resolution: {integrity: sha512-+ZrIAtigVmjYkqZQTThHVlz0+TG6D+GDHWhVKvR2DifjtqJ0i+mb9gjo++hN+fWEQdWNGxKCiBBjwgT4EcXd6A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@node-rs/bcrypt-darwin-arm64@1.9.0': + resolution: {integrity: sha512-CQiS+F9Pa0XozvkXR1g7uXE9QvBOPOplDg0iCCPRYTN9PqA5qYxhwe48G3o+v2UeQceNRrbnEtWuANm7JRqIhw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@node-rs/bcrypt-darwin-x64@1.9.0': + resolution: {integrity: sha512-4pTKGawYd7sNEjdJ7R/R67uwQH1VvwPZ0SSUMmeNHbxD5QlwAPXdDH11q22uzVXsvNFZ6nGQBg8No5OUGpx6Ug==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@node-rs/bcrypt-freebsd-x64@1.9.0': + resolution: {integrity: sha512-UmWzySX4BJhT/B8xmTru6iFif3h0Rpx3TqxRLCcbgmH43r7k5/9QuhpiyzpvKGpKHJCFNm4F3rC2wghvw5FCIg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@node-rs/bcrypt-linux-arm-gnueabihf@1.9.0': + resolution: {integrity: sha512-8qoX4PgBND2cVwsbajoAWo3NwdfJPEXgpCsZQZURz42oMjbGyhhSYbovBCskGU3EBLoC8RA2B1jFWooeYVn5BA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@node-rs/bcrypt-linux-arm64-gnu@1.9.0': + resolution: {integrity: sha512-TuAC6kx0SbcIA4mSEWPi+OCcDjTQUMl213v5gMNlttF+D4ieIZx6pPDGTaMO6M2PDHTeCG0CBzZl0Lu+9b0c7Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@node-rs/bcrypt-linux-arm64-musl@1.9.0': + resolution: {integrity: sha512-/sIvKDABOI8QOEnLD7hIj02BVaNOuCIWBKvxcJOt8+TuwJ6zmY1UI5kSv9d99WbiHjTp97wtAUbZQwauU4b9ew==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@node-rs/bcrypt-linux-x64-gnu@1.9.0': + resolution: {integrity: sha512-DyyhDHDsLBsCKz1tZ1hLvUZSc1DK0FU0v52jK6IBQxrj24WscSU9zZe7ie/V9kdmA4Ep57BfpWX8Dsa2JxGdgQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@node-rs/bcrypt-linux-x64-musl@1.9.0': + resolution: {integrity: sha512-duIiuqQ+Lew8ASSAYm6ZRqcmfBGWwsi81XLUwz86a2HR7Qv6V4yc3ZAUQovAikhjCsIqe8C11JlAZSK6+PlXYg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@node-rs/bcrypt-wasm32-wasi@1.9.0': + resolution: {integrity: sha512-ylaGmn9Wjwv/D5lxtawttx3H6Uu2WTTR7lWlRHGT6Ga/MB1Vj4OjSGUW8G8zIVnKuXpGbZ92pgHlt4HUpSLctw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@node-rs/bcrypt-win32-arm64-msvc@1.9.0': + resolution: {integrity: sha512-2h86gF7QFyEzODuDFml/Dp1MSJoZjxJ4yyT2Erf4NkwsiA5MqowUhUsorRwZhX6+2CtlGa7orbwi13AKMsYndw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@node-rs/bcrypt-win32-ia32-msvc@1.9.0': + resolution: {integrity: sha512-kqxalCvhs4FkN0+gWWfa4Bdy2NQAkfiqq/CEf6mNXC13RSV673Ev9V8sRlQyNpCHCNkeXfOT9pgoBdJmMs9muA==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@node-rs/bcrypt-win32-x64-msvc@1.9.0': + resolution: {integrity: sha512-2y0Tuo6ZAT2Cz8V7DHulSlv1Bip3zbzeXyeur+uR25IRNYXKvI/P99Zl85Fbuu/zzYAZRLLlGTRe6/9IHofe/w==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@node-rs/bcrypt@1.9.0': + resolution: {integrity: sha512-u2OlIxW264bFUfvbFqDz9HZKFjwe8FHFtn7T/U8mYjPZ7DWYpbUB+/dkW/QgYfMSfR0ejkyuWaBBe0coW7/7ig==} + engines: {node: '>= 10'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@paralleldrive/cuid2@2.2.2': + resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@playwright/test@1.47.0': + resolution: {integrity: sha512-SgAdlSwYVpToI4e/IH19IHHWvoijAYH5hu2MWSXptRypLSnzj51PcGD+rsOXFayde4P9ZLi+loXVwArg6IUkCA==} + engines: {node: '>=18'} + hasBin: true + + '@polka/url@1.0.0-next.25': + resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + + '@poppinss/macroable@1.0.2': + resolution: {integrity: sha512-xhhEcEvhQC8mP5oOr5hbE4CmUgmw/IPV1jhpGg2xSkzoFrt9i8YVqBQt9744EFesi5F7pBheWozg63RUBM/5JA==} + engines: {node: '>=18.16.0'} + + '@redis/bloom@1.2.0': + resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/client@1.6.0': + resolution: {integrity: sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==} + engines: {node: '>=14'} + + '@redis/graph@1.1.1': + resolution: {integrity: sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/json@1.0.7': + resolution: {integrity: sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/search@1.2.0': + resolution: {integrity: sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/time-series@1.1.0': + resolution: {integrity: sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@rollup/plugin-commonjs@26.0.1': + resolution: {integrity: sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==} + engines: {node: '>=16.0.0 || 14 >= 14.17'} + peerDependencies: + rollup: ^2.68.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-json@6.1.0': + resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-node-resolve@15.2.3': + resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@5.1.0': + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.21.3': + resolution: {integrity: sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.21.3': + resolution: {integrity: sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.21.3': + resolution: {integrity: sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.21.3': + resolution: {integrity: sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.21.3': + resolution: {integrity: sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.21.3': + resolution: {integrity: sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.21.3': + resolution: {integrity: sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.21.3': + resolution: {integrity: sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.3': + resolution: {integrity: sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.21.3': + resolution: {integrity: sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.21.3': + resolution: {integrity: sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.21.3': + resolution: {integrity: sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.21.3': + resolution: {integrity: sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.21.3': + resolution: {integrity: sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.21.3': + resolution: {integrity: sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.21.3': + resolution: {integrity: sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==} + cpu: [x64] + os: [win32] + + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + + '@sinclair/typebox@0.32.35': + resolution: {integrity: sha512-Ul3YyOTU++to8cgNkttakC0dWvpERr6RYoHO2W47DLbFvrwBDJUY31B1sImH6JZSYc4Kt4PyHtoPNu+vL2r2dA==} + + '@smithy/abort-controller@3.1.2': + resolution: {integrity: sha512-b5g+PNujlfqIib9BjkNB108NyO5aZM/RXjfOCXRCqXQ1oPnIkfvdORrztbGgCZdPe/BN/MKDlrGA7PafKPM2jw==} + engines: {node: '>=16.0.0'} + + '@smithy/chunked-blob-reader-native@3.0.0': + resolution: {integrity: sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==} + + '@smithy/chunked-blob-reader@3.0.0': + resolution: {integrity: sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==} + + '@smithy/config-resolver@3.0.6': + resolution: {integrity: sha512-j7HuVNoRd8EhcFp0MzcUb4fG40C7BcyshH+fAd3Jhd8bINNFvEQYBrZoS/SK6Pun9WPlfoI8uuU2SMz8DsEGlA==} + engines: {node: '>=16.0.0'} + + '@smithy/core@2.4.1': + resolution: {integrity: sha512-7cts7/Oni7aCHebHGiBeWoz5z+vmH+Vx2Z/UW3XtXMslcxI3PEwBZxNinepwZjixS3n12fPc247PHWmjU7ndsQ==} + engines: {node: '>=16.0.0'} + + '@smithy/credential-provider-imds@3.2.1': + resolution: {integrity: sha512-4z/oTWpRF2TqQI3aCM89/PWu3kim58XU4kOCTtuTJnoaS4KT95cPWMxbQfTN2vzcOe96SOKO8QouQW/+ESB1fQ==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-codec@3.1.3': + resolution: {integrity: sha512-mKBrmhg6Zd3j07G9dkKTGmrU7pdJGTNz8LbZtIOR3QoodS5yDNqEqoXU4Eg38snZcnCAh7NPBsw5ndxtJPLiCg==} + + '@smithy/eventstream-serde-browser@3.0.7': + resolution: {integrity: sha512-UC4RQqyM8B0g5cX/xmWtsNgSBmZ13HrzCqoe5Ulcz6R462/egbIdfTXnayik7jkjvwOrCPL1N11Q9S+n68jPLA==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-serde-config-resolver@3.0.4': + resolution: {integrity: sha512-saIs5rtAMpifqL7u7nc5YeE/6gkenzXpSz5NwEyhIesRWtHK+zEuYn9KY8SArZEbPSHyGxvvgKk1z86VzfUGHw==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-serde-node@3.0.6': + resolution: {integrity: sha512-gRKGBdZah3EjZZgWcsTpShq4cZ4Q4JTTe1OPob+jrftmbYj6CvpeydZbH0roO5SvBG8SI3aBZIet9TGN3zUxUw==} + engines: {node: '>=16.0.0'} + + '@smithy/eventstream-serde-universal@3.0.6': + resolution: {integrity: sha512-1jvXd4sFG+zKaL6WqrJXpL6E+oAMafuM5GPd4qF0+ccenZTX3DZugoCCjlooQyTh+TZho2FpdVYUf5J/bB/j6Q==} + engines: {node: '>=16.0.0'} + + '@smithy/fetch-http-handler@3.2.5': + resolution: {integrity: sha512-DjRtGmK8pKQMIo9+JlAKUt14Z448bg8nAN04yKIvlrrpmpRSG57s5d2Y83npks1r4gPtTRNbAFdQCoj9l3P2KQ==} + + '@smithy/hash-blob-browser@3.1.3': + resolution: {integrity: sha512-im9wAU9mANWW0OP0YGqwX3lw0nXG0ngyIcKQ8V/MUz1r7A6uO2lpPqKmAsH4VPGNLP2JPUhj4aW/m5UKkxX/IA==} + + '@smithy/hash-node@3.0.4': + resolution: {integrity: sha512-6FgTVqEfCr9z/7+Em8BwSkJKA2y3krf1em134x3yr2NHWVCo2KYI8tcA53cjeO47y41jwF84ntsEE0Pe6pNKlg==} + engines: {node: '>=16.0.0'} + + '@smithy/hash-stream-node@3.1.3': + resolution: {integrity: sha512-Tz/eTlo1ffqYn+19VaMjDDbmEWqYe4DW1PAWaS8HvgRdO6/k9hxNPt8Wv5laXoilxE20YzKugiHvxHyO6J7kGA==} + engines: {node: '>=16.0.0'} + + '@smithy/invalid-dependency@3.0.4': + resolution: {integrity: sha512-MJBUrojC4SEXi9aJcnNOE3oNAuYNphgCGFXscaCj2TA/59BTcXhzHACP8jnnEU3n4yir/NSLKzxqez0T4x4tjA==} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@3.0.0': + resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} + engines: {node: '>=16.0.0'} + + '@smithy/md5-js@3.0.4': + resolution: {integrity: sha512-qSlqr/+hybufIJgxQW2gYzGE6ywfOxkjjJVojbbmv4MtxfdDFfzRew+NOIOXcYgazW0f8OYBTIKsmNsjxpvnng==} + + '@smithy/middleware-content-length@3.0.6': + resolution: {integrity: sha512-AFyHCfe8rumkJkz+hCOVJmBagNBj05KypyDwDElA4TgMSA4eYDZRjVePFZuyABrJZFDc7uVj3dpFIDCEhf59SA==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-endpoint@3.1.1': + resolution: {integrity: sha512-Irv+soW8NKluAtFSEsF8O3iGyLxa5oOevJb/e1yNacV9H7JP/yHyJuKST5YY2ORS1+W34VR8EuUrOF+K29Pl4g==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-retry@3.0.16': + resolution: {integrity: sha512-08kI36p1yB4CWO3Qi+UQxjzobt8iQJpnruF0K5BkbZmA/N/sJ51A1JJGJ36GgcbFyPfWw2FU48S5ZoqXt0h0jw==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-serde@3.0.4': + resolution: {integrity: sha512-1lPDB2O6IJ50Ucxgn7XrvZXbbuI48HmPCcMTuSoXT1lDzuTUfIuBjgAjpD8YLVMfnrjdepi/q45556LA51Pubw==} + engines: {node: '>=16.0.0'} + + '@smithy/middleware-stack@3.0.4': + resolution: {integrity: sha512-sLMRjtMCqtVcrOqaOZ10SUnlFE25BSlmLsi4bRSGFD7dgR54eqBjfqkVkPBQyrKBortfGM0+2DJoUPcGECR+nQ==} + engines: {node: '>=16.0.0'} + + '@smithy/node-config-provider@3.1.5': + resolution: {integrity: sha512-dq/oR3/LxgCgizVk7in7FGTm0w9a3qM4mg3IIXLTCHeW3fV+ipssSvBZ2bvEx1+asfQJTyCnVLeYf7JKfd9v3Q==} + engines: {node: '>=16.0.0'} + + '@smithy/node-http-handler@3.2.0': + resolution: {integrity: sha512-5TFqaABbiY7uJMKbqR4OARjwI/l4TRoysDJ75pLpVQyO3EcmeloKYwDGyCtgB9WJniFx3BMkmGCB9+j+QiB+Ww==} + engines: {node: '>=16.0.0'} + + '@smithy/property-provider@3.1.4': + resolution: {integrity: sha512-BmhefQbfkSl9DeU0/e6k9N4sT5bya5etv2epvqLUz3eGyfRBhtQq60nDkc1WPp4c+KWrzK721cUc/3y0f2psPQ==} + engines: {node: '>=16.0.0'} + + '@smithy/protocol-http@4.1.1': + resolution: {integrity: sha512-Fm5+8LkeIus83Y8jTL1XHsBGP8sPvE1rEVyKf/87kbOPTbzEDMcgOlzcmYXat2h+nC3wwPtRy8hFqtJS71+Wow==} + engines: {node: '>=16.0.0'} + + '@smithy/querystring-builder@3.0.4': + resolution: {integrity: sha512-NEoPAsZPdpfVbF98qm8i5k1XMaRKeEnO47CaL5ja6Y1Z2DgJdwIJuJkTJypKm/IKfp8gc0uimIFLwhml8+/pAw==} + engines: {node: '>=16.0.0'} + + '@smithy/querystring-parser@3.0.4': + resolution: {integrity: sha512-7CHPXffFcakFzhO0OZs/rn6fXlTHrSDdLhIT6/JIk1u2bvwguTL3fMCc1+CfcbXA7TOhjWXu3TcB1EGMqJQwHg==} + engines: {node: '>=16.0.0'} + + '@smithy/service-error-classification@3.0.4': + resolution: {integrity: sha512-KciDHHKFVTb9A1KlJHBt2F26PBaDtoE23uTZy5qRvPzHPqrooXFi6fmx98lJb3Jl38PuUTqIuCUmmY3pacuMBQ==} + engines: {node: '>=16.0.0'} + + '@smithy/shared-ini-file-loader@3.1.5': + resolution: {integrity: sha512-6jxsJ4NOmY5Du4FD0enYegNJl4zTSuKLiChIMqIkh+LapxiP7lmz5lYUNLE9/4cvA65mbBmtdzZ8yxmcqM5igg==} + engines: {node: '>=16.0.0'} + + '@smithy/signature-v4@4.1.1': + resolution: {integrity: sha512-SH9J9be81TMBNGCmjhrgMWu4YSpQ3uP1L06u/K9SDrE2YibUix1qxedPCxEQu02At0P0SrYDjvz+y91vLG0KRQ==} + engines: {node: '>=16.0.0'} + + '@smithy/smithy-client@3.3.0': + resolution: {integrity: sha512-H32nVo8tIX82kB0xI2LBrIcj8jx/3/ITotNLbeG1UL0b3b440YPR/hUvqjFJiaB24pQrMjRbU8CugqH5sV0hkw==} + engines: {node: '>=16.0.0'} + + '@smithy/types@3.4.0': + resolution: {integrity: sha512-0shOWSg/pnFXPcsSU8ZbaJ4JBHZJPPzLCJxafJvbMVFo9l1w81CqpgUqjlKGNHVrVB7fhIs+WS82JDTyzaLyLA==} + engines: {node: '>=16.0.0'} + + '@smithy/url-parser@3.0.4': + resolution: {integrity: sha512-XdXfObA8WrloavJYtDuzoDhJAYc5rOt+FirFmKBRKaihu7QtU/METAxJgSo7uMK6hUkx0vFnqxV75urtRaLkLg==} + + '@smithy/util-base64@3.0.0': + resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-body-length-browser@3.0.0': + resolution: {integrity: sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==} + + '@smithy/util-body-length-node@3.0.0': + resolution: {integrity: sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@3.0.0': + resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-config-provider@3.0.0': + resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-defaults-mode-browser@3.0.16': + resolution: {integrity: sha512-Os8ddfNBe7hmc5UMWZxygIHCyAqY0aWR8Wnp/aKbti3f8Df/r0J9ttMZIxeMjsFgtVjEryB0q7SGcwBsHk8WEw==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-defaults-mode-node@3.0.16': + resolution: {integrity: sha512-rNhFIYRtrOrrhRlj6RL8jWA6/dcwrbGYAmy8+OAHjjzQ6zdzUBB1P+3IuJAgwWN6Y5GxI+mVXlM/pOjaoIgHow==} + engines: {node: '>= 10.0.0'} + + '@smithy/util-endpoints@2.1.0': + resolution: {integrity: sha512-ilS7/0jcbS2ELdg0fM/4GVvOiuk8/U3bIFXUW25xE1Vh1Ol4DP6vVHQKqM40rCMizCLmJ9UxK+NeJrKlhI3HVA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-hex-encoding@3.0.0': + resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-middleware@3.0.4': + resolution: {integrity: sha512-uSXHTBhstb1c4nHdmQEdkNMv9LiRNaJ/lWV2U/GO+5F236YFpdPw+hyWI9Zc0Rp9XKzwD9kVZvhZmEgp0UCVnA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-retry@3.0.4': + resolution: {integrity: sha512-JJr6g0tO1qO2tCQyK+n3J18r34ZpvatlFN5ULcLranFIBZPxqoivb77EPyNTVwTGMEvvq2qMnyjm4jMIxjdLFg==} + engines: {node: '>=16.0.0'} + + '@smithy/util-stream@3.1.4': + resolution: {integrity: sha512-txU3EIDLhrBZdGfon6E9V6sZz/irYnKFMblz4TLVjyq8hObNHNS2n9a2t7GIrl7d85zgEPhwLE0gANpZsvpsKg==} + engines: {node: '>=16.0.0'} + + '@smithy/util-uri-escape@3.0.0': + resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} + engines: {node: '>=16.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@3.0.0': + resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-waiter@3.1.3': + resolution: {integrity: sha512-OU0YllH51/CxD8iyr3UHSMwYqTGTyuxFdCMH/0F978t+iDmJseC/ttrWPb22zmYkhkrjqtipzC1xaMuax5QKIA==} + engines: {node: '>=16.0.0'} + + '@sodaru/yup-to-json-schema@2.0.1': + resolution: {integrity: sha512-lWb0Wiz8KZ9ip/dY1eUqt7fhTPmL24p6Hmv5Fd9pzlzAdw/YNcWZr+tiCT4oZ4Zyxzi9+1X4zv82o7jYvcFxYA==} + + '@sveltejs/adapter-node@5.2.2': + resolution: {integrity: sha512-BCX4zP0cf86TXpmvLQTnnT/tp7P12UMezf+5LwljP1MJC1fFzn9XOXpAHQCyP+pyHGy2K7p5gY0LyLcZFAL02w==} + peerDependencies: + '@sveltejs/kit': ^2.4.0 + + '@sveltejs/kit@2.5.26': + resolution: {integrity: sha512-8l1JTIM2L+bS8ebq1E+nGjv/YSKSnD9Q19bYIUkc41vaEG2JjVUx6ikvPIJv2hkQAuqJLzoPrXlKk4KcyWOv3Q==} + engines: {node: '>=18.13'} + hasBin: true + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.3 + + '@sveltejs/vite-plugin-svelte-inspector@2.1.0': + resolution: {integrity: sha512-9QX28IymvBlSCqsCll5t0kQVxipsfhFFL+L2t3nTWfXnddYwxBuAEtTtlaVQpRz9c37BhJjltSeY4AJSC03SSg==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3': + resolution: {integrity: sha512-kuGJ2CZ5lAw3gKF8Kw0AfKtUJWbwdlDHY14K413B0MCyrzvQvsKTorwmwZcky0+QqY6RnVIZ/5FttB9bQmkLXg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^4.0.0-next.0||^4.0.0 + svelte: ^5.0.0-next.96 || ^5.0.0 + vite: ^5.0.0 + + '@sveltejs/vite-plugin-svelte@3.1.2': + resolution: {integrity: sha512-Txsm1tJvtiYeLUVRNqxZGKR/mI+CzuIQuc2gn+YCs9rMTowpNZ2Nqt53JdL8KF9bLhAf2ruR/dr9eZCwdTriRA==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + + '@sveltejs/vite-plugin-svelte@4.0.0-next.7': + resolution: {integrity: sha512-yMUnAqquoayvBDztk1rWUgdtvjv7YcHgopCAB7sWl9SQht8U/7lqwTlJU0ZTAY09pFFRe6bbakd7YoiyyIvJiA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} + peerDependencies: + svelte: ^5.0.0-next.96 || ^5.0.0 + vite: ^5.0.0 + + '@swc/helpers@0.5.13': + resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} + + '@tailwindcss/typography@0.5.15': + resolution: {integrity: sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20' + + '@tybys/wasm-util@0.8.3': + resolution: {integrity: sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q==} + + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@22.5.4': + resolution: {integrity: sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/validator@13.12.1': + resolution: {integrity: sha512-w0URwf7BQb0rD/EuiG12KP0bailHKHP5YVviJG9zw3ykAokL0TuxU2TUqMB7EwZ59bDHYdeTIvjI5m0S7qHfOA==} + + '@typescript-eslint/eslint-plugin@8.5.0': + resolution: {integrity: sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@8.5.0': + resolution: {integrity: sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@8.5.0': + resolution: {integrity: sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.5.0': + resolution: {integrity: sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@8.5.0': + resolution: {integrity: sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.5.0': + resolution: {integrity: sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@8.5.0': + resolution: {integrity: sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + '@typescript-eslint/visitor-keys@8.5.0': + resolution: {integrity: sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vinejs/compiler@2.5.0': + resolution: {integrity: sha512-hg4ekaB5Y2zh+IWzBiC/WCDWrIfpVnKu/ubUvelKlidc/VbulsexoFRw5kJGHZenPVI5YzNnDeTdYSALkTV7jQ==} + engines: {node: '>=18.0.0'} + + '@vinejs/vine@1.8.0': + resolution: {integrity: sha512-Qq3XxbA26jzqS9ICifkqzT399lMQZ2fWtqeV3luI2as+UIK7qDifJFU2Q4W3q3IB5VXoWxgwAZSZEO0em9I/qQ==} + engines: {node: '>=18.16.0'} + + '@vitest/expect@2.1.0': + resolution: {integrity: sha512-N3/xR4fSu0+6sVZETEtPT1orUs2+Y477JOXTcU3xKuu3uBlsgbD7/7Mz2LZ1Jr1XjwilEWlrIgSCj4N1+5ZmsQ==} + + '@vitest/mocker@2.1.0': + resolution: {integrity: sha512-ZxENovUqhzl+QiOFpagiHUNUuZ1qPd5yYTCYHomGIZOFArzn4mgX2oxZmiAItJWAaXHG6bbpb/DpSPhlk5DgtA==} + peerDependencies: + '@vitest/spy': 2.1.0 + msw: ^2.3.5 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.1.0': + resolution: {integrity: sha512-7sxf2F3DNYatgmzXXcTh6cq+/fxwB47RIQqZJFoSH883wnVAoccSRT6g+dTKemUBo8Q5N4OYYj1EBXLuRKvp3Q==} + + '@vitest/runner@2.1.0': + resolution: {integrity: sha512-D9+ZiB8MbMt7qWDRJc4CRNNUlne/8E1X7dcKhZVAbcOKG58MGGYVDqAq19xlhNfMFZsW0bpVKgztBwks38Ko0w==} + + '@vitest/snapshot@2.1.0': + resolution: {integrity: sha512-x69CygGMzt9VCO283K2/FYQ+nBrOj66OTKpsPykjCR4Ac3lLV+m85hj9reaIGmjBSsKzVvbxWmjWE3kF5ha3uQ==} + + '@vitest/spy@2.1.0': + resolution: {integrity: sha512-IXX5NkbdgTYTog3F14i2LgnBc+20YmkXMx0IWai84mcxySUDRgm0ihbOfR4L0EVRBDFG85GjmQQEZNNKVVpkZw==} + + '@vitest/utils@2.1.0': + resolution: {integrity: sha512-rreyfVe0PuNqJfKYUwfPDfi6rrp0VSu0Wgvp5WBqJonP+4NvXHk48X6oBam1Lj47Hy6jbJtnMj3OcRdrkTP0tA==} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-typescript@1.4.13: + resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} + peerDependencies: + acorn: '>=8.9.0' + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arctic@1.9.2: + resolution: {integrity: sha512-VTnGpYx+ypboJdNrWnK17WeD7zN/xSCHnpecd5QYsBfVZde/5i+7DJ1wrf/ioSDMiEjagXmyNWAE3V2C9f1hNg==} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.1: + resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} + engines: {node: '>= 0.4'} + + arktype@2.0.0-beta.0: + resolution: {integrity: sha512-fE3ssMiXjr/bLqFPzlDhRlXngdyHQreu7p7i8+dtcY1CA+f8WrVUcue6JxywhnqEJXPG4HOcIwQcC+q4VfeUMQ==} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bits-ui@0.21.13: + resolution: {integrity: sha512-7nmOh6Ig7ND4DXZHv1FhNsY9yUGrad0+mf3tc4YN//3MgnJT1LnHtk4HZAKgmxCOe7txSX7/39LtYHbkrXokAQ==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.118 + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.23.3: + resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + bullmq@5.13.0: + resolution: {integrity: sha512-rE7v3jMZZGsEhfMhLZwADwuHdqJPTTGHBM8C+SpxF9GzyZ+7pvC80EP5bOZJPPRzbmyhvIPJCVd0bchUZiQF+w==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + caniuse-lite@1.0.30001660: + resolution: {integrity: sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==} + + chai@5.1.1: + resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + engines: {node: '>=12'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + + cmdk-sv@0.0.18: + resolution: {integrity: sha512-istixiQSy9Ez/mQ4VXWB69btqNyDZckbd1XFEwR46Vw+n5zjdmvoWAcOTj0uX3FZXtw9ikwLVmfoW2nwwMClRg==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.1 + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + concat-map@0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + cron-parser@4.9.0: + resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} + engines: {node: '>=12.0.0'} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + devalue@5.0.0: + resolution: {integrity: sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dotenv-cli@7.4.2: + resolution: {integrity: sha512-SbUj8l61zIbzyhIbg0FwPJq6+wjbzdn9oEtozQpZ6kW2ihCcapKVZj49oCT3oPM+mgQm+itgvUQcG5szxVrZTA==} + hasBin: true + + dotenv-expand@10.0.0: + resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} + engines: {node: '>=12'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + drizzle-kit@0.26.2: + resolution: {integrity: sha512-cMq8omEKywjIy5KcqUo6LvEFxkl8/zYHsgYjFVXjmPWWtuW4blcz+YW9+oIhoaALgs2ebRjzXwsJgN9i6P49Dw==} + hasBin: true + + drizzle-orm@0.35.1: + resolution: {integrity: sha512-HQxDdYuXlZFuvDPztlUIzrX8TqWa/Ej6uN6L0hkbuGL4slexOUMc3u4nXVU15RQ5QYbk+uLQnR6v1+OIrdCTXQ==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@electric-sql/pglite': '>=0.1.1' + '@libsql/client': '>=0.10.0' + '@neondatabase/serverless': '>=0.1' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/react': '>=18' + '@types/sql.js': '*' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=13.2.0' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + react: '>=18' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/react': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + react: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.21: + resolution: {integrity: sha512-+rBAerCpQvFSPyAO677i5gJuWGO2WFsoujENdcMzsrpP7Ebcc3pmpERgU8CV4fFF10a5haP4ivnFQ/AmLICBVg==} + + embla-carousel-reactive-utils@8.2.1: + resolution: {integrity: sha512-LXMVOOyv09ZKRxRQXYMX1FpVGcypsuxdcidNcNlBQUN2mK7hkmjVFQwwhfnnY39KMi88XYnYPBgMxfTe0vxSrA==} + peerDependencies: + embla-carousel: 8.2.1 + + embla-carousel-svelte@8.2.1: + resolution: {integrity: sha512-4HTJizrP418lKN6H7nXK4Sy4I8eDKWkXDRrGiAtQ3mn5tZjzZ2+Lej+pP7BeAgri0m7OXUUGcARcy3lEmf2JZA==} + peerDependencies: + svelte: ^3.49.0 || ^4.0.0 + + embla-carousel@8.2.1: + resolution: {integrity: sha512-9mTDtyMZJhFuuW5pixhTT4iLiJB1l3dH3IpXUKCsgLlRlHCiySf/wLKy5xIAzmxIsokcQ50xea8wi7BCt0+Rxg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild-runner@2.2.2: + resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} + hasBin: true + peerDependencies: + esbuild: '*' + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-svelte@2.43.0: + resolution: {integrity: sha512-REkxQWvg2pp7QVLxQNa+dJ97xUqRe7Y2JJbSWkHSuszu0VcblZtXkPBPckkivk99y5CdLw4slqfPylL2d/X4jQ==} + engines: {node: ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.191 + peerDependenciesMeta: + svelte: + optional: true + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@8.0.2: + resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.10.0: + resolution: {integrity: sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esm-env@1.0.0: + resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} + + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrap@1.2.2: + resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + express-rate-limit@7.4.0: + resolution: {integrity: sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==} + engines: {node: '>= 16'} + peerDependencies: + express: 4 || 5 || ^5.0.0-beta.1 + + express@4.21.0: + resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==} + engines: {node: '>= 0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-xml-parser@4.4.1: + resolution: {integrity: sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==} + hasBin: true + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fdir@6.3.0: + resolution: {integrity: sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + focus-trap@7.6.0: + resolution: {integrity: sha512-1td0l3pMkWJLFipobUcGaf+5DTY4PLDDrcqoSaKP8ediO/CoWCCYk/fT/Y2A4e6TNB+Sh6clRJCjOPPnKoNHnQ==} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + formsnap@1.0.1: + resolution: {integrity: sha512-TvU9CoLSiacW1c7wXhLiyVpyy/LBfG0CEFDbs3M3jrsxBSrkTpsuhbQ8JYKY3CNCmIhZlgxCH+Vqr7RBF9G53w==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.1 + sveltekit-superforms: ^2.3.0 + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hono-rate-limiter@0.4.0: + resolution: {integrity: sha512-7RWU2HZvxPtfBrvjXKDiQ3F6ZH8k49JhxVkHquUz5UZKjauj5PrP29MvISykThtfpy4mGG6kqxFBHW1ed9wwnA==} + peerDependencies: + hono: ^4.1.1 + + hono@4.6.1: + resolution: {integrity: sha512-6NGwvttY1+HAFii08VYiEKI6ETPAFbpLntpm2M/MogEsAFWdZV74UNT+2M4bmqX90cIQhjlpBSP+tO+CfB0uww==} + engines: {node: '>=16.0.0'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ioredis@5.4.1: + resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==} + engines: {node: '>=12.22.0'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonpath-plus@7.2.0: + resolution: {integrity: sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==} + engines: {node: '>=12.0.0'} + + just-clone@6.2.0: + resolution: {integrity: sha512-1IynUYEc/HAwxhi3WDpIpxJbZpMCvvrrmZVqvj9EhpvbH8lls7HhdhiByjL7DkAaWlLIzpC0Xc/VPvy/UxLNjA==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + known-css-properties@0.34.0: + resolution: {integrity: sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.1.1: + resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lucia@3.2.0: + resolution: {integrity: sha512-eXMxXwk6hqtjRTj4W/x3EnTUtAztLPm0p2N2TEBMDEbakDLXiYnDQ9z/qahjPdPdhPguQc+vwO0/88zIWxlpuw==} + + lucide-svelte@0.441.0: + resolution: {integrity: sha512-lwckKpu4KNth7EBPWUdx7dvRaBrFC173JSdioN2WILol7nwFAPfvbGLeez8ZlnT31boj7pNT7hjvBz3ZJfmUbQ==} + peerDependencies: + svelte: ^3 || ^4 || ^5.0.0-next.42 + + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs-browser@3.5.10302: + resolution: {integrity: sha512-JJTc/nh3ig05O0gBBGZjTCPOyydaTxNF0uHYBrcc1gHNnO+KIHIvo0Y1FKCJsaei6FCl8C6xfQomXqu+cuzkIw==} + + memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + + memoize-weak@1.0.2: + resolution: {integrity: sha512-gj39xkrjEw7nCn4nJ1M5ms6+MyMlyiGmttzsqAUsAKn6bYKwuTHh/AO3cKPF8IBrTIYTxb0wWXFs3E//Y8VoWQ==} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mode-watcher@0.4.1: + resolution: {integrity: sha512-bNC+1NXmwEFZtziCdZSgP7HFQTpqJPcQn9GwwJQGSf6SBF3neEPYV1uRwkYuAQwbsvsXIYtzaqgedDzJ7D1mhg==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.1 + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + msgpackr-extract@3.0.3: + resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + hasBin: true + + msgpackr@1.11.0: + resolution: {integrity: sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.0.7: + resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==} + engines: {node: ^18 || >=20} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + + node-gyp-build-optional-packages@5.2.2: + resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} + hasBin: true + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + oslo@1.2.0: + resolution: {integrity: sha512-OoFX6rDsNcOQVAD2gQD/z03u4vEjWZLzJtwkmgfRF+KpQUXwdgEXErD7zNhyowmHwHefP+PM9Pw13pgpHMRlzw==} + + oslo@1.2.1: + resolution: {integrity: sha512-HfIhB5ruTdQv0XX2XlncWQiJ5SIHZ7NHZhVyHth0CSZ/xzge00etRyYy/3wp/Dsu+PkxMC+6+B2lS/GcKoewkA==} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + + paneforge@0.0.5: + resolution: {integrity: sha512-98QHobaN/KeQhqqglbvjUmNCTRC4h4iqDxpSV8jCGhRLttgGlRXZNzWNr4Firni5rwasAZjOza0k/JdwppB/AQ==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.1 + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.10: + resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + pg-cloudflare@1.1.1: + resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} + + pg-connection-string@2.6.4: + resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-pool@3.6.2: + resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==} + peerDependencies: + pg: '>=8.0' + + pg-protocol@1.6.1: + resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + pg@8.12.0: + resolution: {integrity: sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==} + engines: {node: '>= 8.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + + pgpass@1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + playwright-core@1.47.0: + resolution: {integrity: sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.47.0: + resolution: {integrity: sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==} + engines: {node: '>=18'} + hasBin: true + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-safe-parser@6.0.0: + resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.3.3 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.45: + resolution: {integrity: sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==} + engines: {node: ^10 || ^12 || >=14} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + postgres@3.4.4: + resolution: {integrity: sha512-IbyN+9KslkqcXa8AO9fxpk97PA4pzewvpi2B3Dwy9u4zpV32QicaEdgmF3eSQUzdRk7ttDHQejNgAEr4XoeH4A==} + engines: {node: '>=12'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-plugin-svelte@3.2.6: + resolution: {integrity: sha512-Y1XWLw7vXUQQZmgv1JAEiLcErqUniAF2wO7QJsw8BVMvpLET2dI5WpEIEJx1r11iHVdSMzQxivyfrH9On9t2IQ==} + peerDependencies: + prettier: ^3.0.0 + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + + prettier-plugin-tailwindcss@0.6.6: + resolution: {integrity: sha512-OPva5S7WAsPLEsOuOWXATi13QrCKACCiIonFgIR6V4lYv4QLp++UXVhZSzRbZxXGimkQtQT86CC6fQqTOybGng==} + engines: {node: '>=14.21.3'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig-melody': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-import-sort: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-style-order: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig-melody': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-import-sort: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-style-order: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + + property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + rate-limit-redis@4.2.0: + resolution: {integrity: sha512-wV450NQyKC24NmPosJb2131RoczLdfIJdKCReNwtVpm5998U8SgKrAZrIHaN/NfQgqOHaan8Uq++B4sa5REwjA==} + engines: {node: '>= 16'} + peerDependencies: + express-rate-limit: '>= 6' + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-om@0.4.6: + resolution: {integrity: sha512-L6cfZfG+I7ES+hHfBBKQwUEbfmGQJhIvcreP5NgxkxX+LtYLLXrcpP/sIIW1jMyjdgJE1KRjAbiyiuL2AAHe3g==} + engines: {node: '>= 14'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + + redis@4.7.0: + resolution: {integrity: sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.21.3: + resolution: {integrity: sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-cookie-parser@2.7.0: + resolution: {integrity: sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + superstruct@2.0.2: + resolution: {integrity: sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==} + engines: {node: '>=14.0.0'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svelte-check@4.0.2: + resolution: {integrity: sha512-w2yqcG9ELJe2RJCnAvB7v0OgkHhL3czzz/tVoxGFfO6y4mOrF6QHCDhXijeXzsU7LVKEwWS3Qd9tza4JBuDxqA==} + engines: {node: '>= 18.0.0'} + hasBin: true + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + typescript: '>=5.0.0' + + svelte-dnd-action@0.9.50: + resolution: {integrity: sha512-EnUyBmiMjflGr+NKfPmPpyareKEbQkdVGRTv6YyBHIEXPOv92XHgPHubErQ1tOaXaZ2c7y4Gja85uA1/Desw/Q==} + peerDependencies: + svelte: '>=3.23.0 || ^5.0.0-next.0' + + svelte-eslint-parser@0.41.0: + resolution: {integrity: sha512-L6f4hOL+AbgfBIB52Z310pg1d2QjRqm7wy3kI1W6hhdhX5bvu7+f0R6w4ykp5HoDdzq+vGhIJmsisaiJDGmVfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.191 + peerDependenciesMeta: + svelte: + optional: true + + svelte-hmr@0.16.0: + resolution: {integrity: sha512-Gyc7cOS3VJzLlfj7wKS0ZnzDVdv3Pn2IuVeJPk9m2skfhcu5bq3wtIZyQGggr7/Iim5rH5cncyQft/kRLupcnA==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + + svelte-sonner@0.3.28: + resolution: {integrity: sha512-K3AmlySeFifF/cKgsYNv5uXqMVNln0NBAacOYgmkQStLa/UoU0LhfAACU6Gr+YYC8bOCHdVmFNoKuDbMEsppJg==} + peerDependencies: + svelte: ^3.0.0 || ^4.0.0 || ^5.0.0-next.1 + + svelte@5.0.0-next.164: + resolution: {integrity: sha512-e+V1dSZLCCu0Ln7RKwSl/zP9ZZFbDGW7ABfGQYU/+6sWponizQocmyHyKHzctor0ruGgJKOF7QQB+M6lE2+UrA==} + engines: {node: '>=18'} + + sveltekit-search-params@3.0.0: + resolution: {integrity: sha512-wq1Yo5zITev8ty9CWGmHgvAh+Xb3mCUewyUmvCdv6MJWi+/aZ4o79Y6SjuduDL0Cfd/KYHkqt4f/wQ4FtokSdw==} + peerDependencies: + '@sveltejs/kit': ^1.0.0 || ^2.0.0 + svelte: ^3.55.0 || ^4.0.0 || ^5.0.0 + + sveltekit-superforms@2.17.0: + resolution: {integrity: sha512-QrX8pkcmE0XoeVU42zMhsah4FoDrgtPc/4cZEr38rDlgU+DE0xNc5J0E7z1456sUJNbFjaB0+HZwwAkX0vYqaA==} + peerDependencies: + '@sveltejs/kit': 1.x || 2.x + svelte: 3.x || 4.x || >=5.0.0-next.51 + + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + + tailwind-merge@2.5.2: + resolution: {integrity: sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg==} + + tailwind-variants@0.2.1: + resolution: {integrity: sha512-2xmhAf4UIc3PijOUcJPA1LP4AbxhpcHuHM2C26xM0k81r0maAO6uoUSHl3APmvHZcY5cZCY/bYuJdfFa4eGoaw==} + engines: {node: '>=16.x', pnpm: '>=7.x'} + peerDependencies: + tailwindcss: '*' + + tailwindcss@3.4.11: + resolution: {integrity: sha512-qhEuBcLemjSJk5ajccN9xJFtM/h0AVCPaA6C92jNP+M2J8kX+eMJHI7R2HFKUvvAsMpcfLILMCFYSeDwpMmlUg==} + engines: {node: '>=14.0.0'} + hasBin: true + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + + tiny-glob@0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.0: + resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} + + tinypool@1.0.1: + resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-deepmerge@7.0.1: + resolution: {integrity: sha512-JBFCmNenZdUCc+TRNCtXVM6N8y/nDQHAcpj5BlwXG/gnogjam1NunulB9ia68mnqYI446giMfpqeBFFkOleh+g==} + engines: {node: '>=14.13.1'} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tsyringe@4.8.0: + resolution: {integrity: sha512-YB1FG+axdxADa3ncEtRnQCFq/M0lALGLxSZeVNbTU8NqhOVc51nnv2CISTcvc1kyv6EGPtXVr0v6lWeDxiijOA==} + engines: {node: '>= 6.0.0'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + engines: {node: '>=14.17'} + hasBin: true + + ulid@2.3.0: + resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} + hasBin: true + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + update-browserslist-db@1.1.0: + resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + valibot@0.31.1: + resolution: {integrity: sha512-2YYIhPrnVSz/gfT2/iXVTrSj92HwchCt9Cga/6hX4B26iCz9zkIsGTS0HjDYTZfTi1Un0X6aRvhBi1cfqs/i0Q==} + + valibot@0.35.0: + resolution: {integrity: sha512-+i2aCRkReTrd5KBN/dW2BrPOvFnU5LXTV2xjZnjnqUIO8YUx6P2+MgRrkwF2FhkexgyKq/NIZdPdknhHf5A/Ww==} + + validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vaul-svelte@0.3.2: + resolution: {integrity: sha512-X4OGWttSTVUl417qGDsSFgOvIx24DoiMRY/jaP9z0v9FL8LQQJ0RQ1ZM0QpdyQPRlNd24ewjNQHh5EgYDtfNpw==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.1 + + vite-node@2.1.0: + resolution: {integrity: sha512-+ybYqBVUjYyIscoLzMWodus2enQDZOpGhcU6HdOVD6n8WZdk12w1GFL3mbnxLs7hPtRtqs1Wo5YF6/Tsr6fmhg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.4.4: + resolution: {integrity: sha512-RHFCkULitycHVTtelJ6jQLd+KSAAzOgEYorV32R2q++M6COBjKJR6BxqClwp5sf0XaBDjVMuJ9wnNfyAJwjMkA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitefu@0.2.5: + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitefu@1.0.2: + resolution: {integrity: sha512-0/iAvbXyM3RiPPJ4lyD4w6Mjgtf4ejTK6TPvTNG3H32PLwuT0N/ZjJLiXug7ETE/LWtTeHw9WRv7uX/tIKYyKg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest@2.1.0: + resolution: {integrity: sha512-XuuEeyNkqbfr0FtAvd9vFbInSSNY1ykCQTYQ0sj9wPy4hx+1gR7gqVNdW0AX2wrrM1wWlN5fnJDjF9xG6mYRSQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.0 + '@vitest/ui': 2.1.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yup@1.4.0: + resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} + + zimmerframe@1.1.2: + resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} + + zod-to-json-schema@3.23.3: + resolution: {integrity: sha512-TYWChTxKQbRJp5ST22o/Irt9KC5nj7CdBKYB/AosCRdj/wxEMvv4NNaj9XVUHDOIp53ZxArGhnw5HMZziPFjog==} + peerDependencies: + zod: ^3.23.3 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@ark/schema@0.2.0': + dependencies: + '@ark/util': 0.1.0 + optional: true + + '@ark/util@0.1.0': + optional: true + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.649.0 + tslib: 2.7.0 + + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.649.0 + tslib: 2.7.0 + + '@aws-crypto/sha1-browser@5.2.0': + dependencies: + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-locate-window': 3.568.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.7.0 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-locate-window': 3.568.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.7.0 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.649.0 + tslib: 2.7.0 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.7.0 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.7.0 + + '@aws-sdk/client-s3@3.651.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.650.0(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/client-sts': 3.650.0 + '@aws-sdk/core': 3.649.0 + '@aws-sdk/credential-provider-node': 3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/middleware-bucket-endpoint': 3.649.0 + '@aws-sdk/middleware-expect-continue': 3.649.0 + '@aws-sdk/middleware-flexible-checksums': 3.651.0 + '@aws-sdk/middleware-host-header': 3.649.0 + '@aws-sdk/middleware-location-constraint': 3.649.0 + '@aws-sdk/middleware-logger': 3.649.0 + '@aws-sdk/middleware-recursion-detection': 3.649.0 + '@aws-sdk/middleware-sdk-s3': 3.649.0 + '@aws-sdk/middleware-ssec': 3.649.0 + '@aws-sdk/middleware-user-agent': 3.649.0 + '@aws-sdk/region-config-resolver': 3.649.0 + '@aws-sdk/signature-v4-multi-region': 3.649.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-endpoints': 3.649.0 + '@aws-sdk/util-user-agent-browser': 3.649.0 + '@aws-sdk/util-user-agent-node': 3.649.0 + '@aws-sdk/xml-builder': 3.649.0 + '@smithy/config-resolver': 3.0.6 + '@smithy/core': 2.4.1 + '@smithy/eventstream-serde-browser': 3.0.7 + '@smithy/eventstream-serde-config-resolver': 3.0.4 + '@smithy/eventstream-serde-node': 3.0.6 + '@smithy/fetch-http-handler': 3.2.5 + '@smithy/hash-blob-browser': 3.1.3 + '@smithy/hash-node': 3.0.4 + '@smithy/hash-stream-node': 3.1.3 + '@smithy/invalid-dependency': 3.0.4 + '@smithy/md5-js': 3.0.4 + '@smithy/middleware-content-length': 3.0.6 + '@smithy/middleware-endpoint': 3.1.1 + '@smithy/middleware-retry': 3.0.16 + '@smithy/middleware-serde': 3.0.4 + '@smithy/middleware-stack': 3.0.4 + '@smithy/node-config-provider': 3.1.5 + '@smithy/node-http-handler': 3.2.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/url-parser': 3.0.4 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.16 + '@smithy/util-defaults-mode-node': 3.0.16 + '@smithy/util-endpoints': 2.1.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-retry': 3.0.4 + '@smithy/util-stream': 3.1.4 + '@smithy/util-utf8': 3.0.0 + '@smithy/util-waiter': 3.1.3 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0)': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sts': 3.650.0 + '@aws-sdk/core': 3.649.0 + '@aws-sdk/credential-provider-node': 3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/middleware-host-header': 3.649.0 + '@aws-sdk/middleware-logger': 3.649.0 + '@aws-sdk/middleware-recursion-detection': 3.649.0 + '@aws-sdk/middleware-user-agent': 3.649.0 + '@aws-sdk/region-config-resolver': 3.649.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-endpoints': 3.649.0 + '@aws-sdk/util-user-agent-browser': 3.649.0 + '@aws-sdk/util-user-agent-node': 3.649.0 + '@smithy/config-resolver': 3.0.6 + '@smithy/core': 2.4.1 + '@smithy/fetch-http-handler': 3.2.5 + '@smithy/hash-node': 3.0.4 + '@smithy/invalid-dependency': 3.0.4 + '@smithy/middleware-content-length': 3.0.6 + '@smithy/middleware-endpoint': 3.1.1 + '@smithy/middleware-retry': 3.0.16 + '@smithy/middleware-serde': 3.0.4 + '@smithy/middleware-stack': 3.0.4 + '@smithy/node-config-provider': 3.1.5 + '@smithy/node-http-handler': 3.2.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/url-parser': 3.0.4 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.16 + '@smithy/util-defaults-mode-node': 3.0.16 + '@smithy/util-endpoints': 2.1.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-retry': 3.0.4 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.650.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.649.0 + '@aws-sdk/middleware-host-header': 3.649.0 + '@aws-sdk/middleware-logger': 3.649.0 + '@aws-sdk/middleware-recursion-detection': 3.649.0 + '@aws-sdk/middleware-user-agent': 3.649.0 + '@aws-sdk/region-config-resolver': 3.649.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-endpoints': 3.649.0 + '@aws-sdk/util-user-agent-browser': 3.649.0 + '@aws-sdk/util-user-agent-node': 3.649.0 + '@smithy/config-resolver': 3.0.6 + '@smithy/core': 2.4.1 + '@smithy/fetch-http-handler': 3.2.5 + '@smithy/hash-node': 3.0.4 + '@smithy/invalid-dependency': 3.0.4 + '@smithy/middleware-content-length': 3.0.6 + '@smithy/middleware-endpoint': 3.1.1 + '@smithy/middleware-retry': 3.0.16 + '@smithy/middleware-serde': 3.0.4 + '@smithy/middleware-stack': 3.0.4 + '@smithy/node-config-provider': 3.1.5 + '@smithy/node-http-handler': 3.2.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/url-parser': 3.0.4 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.16 + '@smithy/util-defaults-mode-node': 3.0.16 + '@smithy/util-endpoints': 2.1.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-retry': 3.0.4 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sts@3.650.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.650.0(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/core': 3.649.0 + '@aws-sdk/credential-provider-node': 3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/middleware-host-header': 3.649.0 + '@aws-sdk/middleware-logger': 3.649.0 + '@aws-sdk/middleware-recursion-detection': 3.649.0 + '@aws-sdk/middleware-user-agent': 3.649.0 + '@aws-sdk/region-config-resolver': 3.649.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-endpoints': 3.649.0 + '@aws-sdk/util-user-agent-browser': 3.649.0 + '@aws-sdk/util-user-agent-node': 3.649.0 + '@smithy/config-resolver': 3.0.6 + '@smithy/core': 2.4.1 + '@smithy/fetch-http-handler': 3.2.5 + '@smithy/hash-node': 3.0.4 + '@smithy/invalid-dependency': 3.0.4 + '@smithy/middleware-content-length': 3.0.6 + '@smithy/middleware-endpoint': 3.1.1 + '@smithy/middleware-retry': 3.0.16 + '@smithy/middleware-serde': 3.0.4 + '@smithy/middleware-stack': 3.0.4 + '@smithy/node-config-provider': 3.1.5 + '@smithy/node-http-handler': 3.2.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/url-parser': 3.0.4 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.16 + '@smithy/util-defaults-mode-node': 3.0.16 + '@smithy/util-endpoints': 2.1.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-retry': 3.0.4 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.649.0': + dependencies: + '@smithy/core': 2.4.1 + '@smithy/node-config-provider': 3.1.5 + '@smithy/property-provider': 3.1.4 + '@smithy/protocol-http': 4.1.1 + '@smithy/signature-v4': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/util-middleware': 3.0.4 + fast-xml-parser: 4.4.1 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-env@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/property-provider': 3.1.4 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-http@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/fetch-http-handler': 3.2.5 + '@smithy/node-http-handler': 3.2.0 + '@smithy/property-provider': 3.1.4 + '@smithy/protocol-http': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/util-stream': 3.1.4 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-ini@3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))(@aws-sdk/client-sts@3.650.0)': + dependencies: + '@aws-sdk/client-sts': 3.650.0 + '@aws-sdk/credential-provider-env': 3.649.0 + '@aws-sdk/credential-provider-http': 3.649.0 + '@aws-sdk/credential-provider-process': 3.649.0 + '@aws-sdk/credential-provider-sso': 3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0)) + '@aws-sdk/credential-provider-web-identity': 3.649.0(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/types': 3.649.0 + '@smithy/credential-provider-imds': 3.2.1 + '@smithy/property-provider': 3.1.4 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + + '@aws-sdk/credential-provider-node@3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))(@aws-sdk/client-sts@3.650.0)': + dependencies: + '@aws-sdk/credential-provider-env': 3.649.0 + '@aws-sdk/credential-provider-http': 3.649.0 + '@aws-sdk/credential-provider-ini': 3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/credential-provider-process': 3.649.0 + '@aws-sdk/credential-provider-sso': 3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0)) + '@aws-sdk/credential-provider-web-identity': 3.649.0(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/types': 3.649.0 + '@smithy/credential-provider-imds': 3.2.1 + '@smithy/property-provider': 3.1.4 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - '@aws-sdk/client-sts' + - aws-crt + + '@aws-sdk/credential-provider-process@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/property-provider': 3.1.4 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/credential-provider-sso@3.650.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))': + dependencies: + '@aws-sdk/client-sso': 3.650.0 + '@aws-sdk/token-providers': 3.649.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0)) + '@aws-sdk/types': 3.649.0 + '@smithy/property-provider': 3.1.4 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.649.0(@aws-sdk/client-sts@3.650.0)': + dependencies: + '@aws-sdk/client-sts': 3.650.0 + '@aws-sdk/types': 3.649.0 + '@smithy/property-provider': 3.1.4 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-bucket-endpoint@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-arn-parser': 3.568.0 + '@smithy/node-config-provider': 3.1.5 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + '@smithy/util-config-provider': 3.0.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-expect-continue@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-flexible-checksums@3.651.0': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-sdk/types': 3.649.0 + '@smithy/is-array-buffer': 3.0.0 + '@smithy/node-config-provider': 3.1.5 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-host-header@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-location-constraint@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-logger@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-recursion-detection@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-sdk-s3@3.649.0': + dependencies: + '@aws-sdk/core': 3.649.0 + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-arn-parser': 3.568.0 + '@smithy/core': 2.4.1 + '@smithy/node-config-provider': 3.1.5 + '@smithy/protocol-http': 4.1.1 + '@smithy/signature-v4': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-stream': 3.1.4 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-ssec@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/middleware-user-agent@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@aws-sdk/util-endpoints': 3.649.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/region-config-resolver@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/node-config-provider': 3.1.5 + '@smithy/types': 3.4.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.4 + tslib: 2.7.0 + + '@aws-sdk/signature-v4-multi-region@3.649.0': + dependencies: + '@aws-sdk/middleware-sdk-s3': 3.649.0 + '@aws-sdk/types': 3.649.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/signature-v4': 4.1.1 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/token-providers@3.649.0(@aws-sdk/client-sso-oidc@3.650.0(@aws-sdk/client-sts@3.650.0))': + dependencies: + '@aws-sdk/client-sso-oidc': 3.650.0(@aws-sdk/client-sts@3.650.0) + '@aws-sdk/types': 3.649.0 + '@smithy/property-provider': 3.1.4 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/types@3.649.0': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/util-arn-parser@3.568.0': + dependencies: + tslib: 2.7.0 + + '@aws-sdk/util-endpoints@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/types': 3.4.0 + '@smithy/util-endpoints': 2.1.0 + tslib: 2.7.0 + + '@aws-sdk/util-locate-window@3.568.0': + dependencies: + tslib: 2.7.0 + + '@aws-sdk/util-user-agent-browser@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/types': 3.4.0 + bowser: 2.11.0 + tslib: 2.7.0 + + '@aws-sdk/util-user-agent-node@3.649.0': + dependencies: + '@aws-sdk/types': 3.649.0 + '@smithy/node-config-provider': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@aws-sdk/xml-builder@3.649.0': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@babel/runtime@7.25.6': + dependencies: + regenerator-runtime: 0.14.1 + optional: true + + '@drizzle-team/brocli@0.10.1': {} + + '@emnapi/core@0.45.0': + dependencies: + tslib: 2.7.0 + optional: true + + '@emnapi/runtime@0.45.0': + dependencies: + tslib: 2.7.0 + optional: true + + '@esbuild-kit/core-utils@3.3.2': + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.6.5': + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.8.1 + + '@esbuild/aix-ppc64@0.19.12': + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.23.1': + optional: true + + '@esbuild/android-arm64@0.18.20': + optional: true + + '@esbuild/android-arm64@0.19.12': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.23.1': + optional: true + + '@esbuild/android-arm@0.18.20': + optional: true + + '@esbuild/android-arm@0.19.12': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.23.1': + optional: true + + '@esbuild/android-x64@0.18.20': + optional: true + + '@esbuild/android-x64@0.19.12': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.23.1': + optional: true + + '@esbuild/darwin-arm64@0.18.20': + optional: true + + '@esbuild/darwin-arm64@0.19.12': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.23.1': + optional: true + + '@esbuild/darwin-x64@0.18.20': + optional: true + + '@esbuild/darwin-x64@0.19.12': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.23.1': + optional: true + + '@esbuild/freebsd-arm64@0.18.20': + optional: true + + '@esbuild/freebsd-arm64@0.19.12': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.23.1': + optional: true + + '@esbuild/freebsd-x64@0.18.20': + optional: true + + '@esbuild/freebsd-x64@0.19.12': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.23.1': + optional: true + + '@esbuild/linux-arm64@0.18.20': + optional: true + + '@esbuild/linux-arm64@0.19.12': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.23.1': + optional: true + + '@esbuild/linux-arm@0.18.20': + optional: true + + '@esbuild/linux-arm@0.19.12': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.23.1': + optional: true + + '@esbuild/linux-ia32@0.18.20': + optional: true + + '@esbuild/linux-ia32@0.19.12': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.23.1': + optional: true + + '@esbuild/linux-loong64@0.18.20': + optional: true + + '@esbuild/linux-loong64@0.19.12': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.23.1': + optional: true + + '@esbuild/linux-mips64el@0.18.20': + optional: true + + '@esbuild/linux-mips64el@0.19.12': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.23.1': + optional: true + + '@esbuild/linux-ppc64@0.18.20': + optional: true + + '@esbuild/linux-ppc64@0.19.12': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.23.1': + optional: true + + '@esbuild/linux-riscv64@0.18.20': + optional: true + + '@esbuild/linux-riscv64@0.19.12': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.23.1': + optional: true + + '@esbuild/linux-s390x@0.18.20': + optional: true + + '@esbuild/linux-s390x@0.19.12': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.23.1': + optional: true + + '@esbuild/linux-x64@0.18.20': + optional: true + + '@esbuild/linux-x64@0.19.12': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.23.1': + optional: true + + '@esbuild/netbsd-x64@0.18.20': + optional: true + + '@esbuild/netbsd-x64@0.19.12': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + + '@esbuild/openbsd-x64@0.18.20': + optional: true + + '@esbuild/openbsd-x64@0.19.12': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.23.1': + optional: true + + '@esbuild/sunos-x64@0.18.20': + optional: true + + '@esbuild/sunos-x64@0.19.12': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.23.1': + optional: true + + '@esbuild/win32-arm64@0.18.20': + optional: true + + '@esbuild/win32-arm64@0.19.12': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.23.1': + optional: true + + '@esbuild/win32-ia32@0.18.20': + optional: true + + '@esbuild/win32-ia32@0.19.12': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.23.1': + optional: true + + '@esbuild/win32-x64@0.18.20': + optional: true + + '@esbuild/win32-x64@0.19.12': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.23.1': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@9.10.0(jiti@1.21.6))': + dependencies: + eslint: 9.10.0(jiti@1.21.6) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.11.0': {} + + '@eslint/config-array@0.18.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.7 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@3.1.0': + dependencies: + ajv: 6.12.6 + debug: 4.3.7 + espree: 10.1.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.10.0': {} + + '@eslint/object-schema@2.1.4': {} + + '@eslint/plugin-kit@0.1.0': + dependencies: + levn: 0.4.1 + + '@exodus/schemasafe@1.3.0': + optional: true + + '@floating-ui/core@1.6.7': + dependencies: + '@floating-ui/utils': 0.2.7 + + '@floating-ui/dom@1.6.10': + dependencies: + '@floating-ui/core': 1.6.7 + '@floating-ui/utils': 0.2.7 + + '@floating-ui/utils@0.2.7': {} + + '@gcornut/valibot-json-schema@0.31.0': + dependencies: + valibot: 0.31.1 + optionalDependencies: + '@types/json-schema': 7.0.15 + esbuild: 0.23.1 + esbuild-runner: 2.2.2(esbuild@0.23.1) + optional: true + + '@hapi/hoek@9.3.0': + optional: true + + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + optional: true + + '@hono/zod-validator@0.2.2(hono@4.6.1)(zod@3.23.8)': + dependencies: + hono: 4.6.1 + zod: 3.23.8 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.0': {} + + '@internationalized/date@3.5.5': + dependencies: + '@swc/helpers': 0.5.13 + + '@ioredis/commands@1.2.0': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@lucia-auth/adapter-drizzle@1.1.0(drizzle-orm@0.35.1(pg@8.12.0)(postgres@3.4.4)(react@18.3.1))(lucia@3.2.0)': + dependencies: + drizzle-orm: 0.35.1(pg@8.12.0)(postgres@3.4.4)(react@18.3.1) + lucia: 3.2.0 + + '@melt-ui/svelte@0.76.2(svelte@5.0.0-next.164)': + dependencies: + '@floating-ui/core': 1.6.7 + '@floating-ui/dom': 1.6.10 + '@internationalized/date': 3.5.5 + dequal: 2.0.3 + focus-trap: 7.6.0 + nanoid: 5.0.7 + svelte: 5.0.0-next.164 + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + optional: true + + '@noble/hashes@1.5.0': {} + + '@node-rs/argon2-android-arm-eabi@1.7.0': + optional: true + + '@node-rs/argon2-android-arm64@1.7.0': + optional: true + + '@node-rs/argon2-darwin-arm64@1.7.0': + optional: true + + '@node-rs/argon2-darwin-x64@1.7.0': + optional: true + + '@node-rs/argon2-freebsd-x64@1.7.0': + optional: true + + '@node-rs/argon2-linux-arm-gnueabihf@1.7.0': + optional: true + + '@node-rs/argon2-linux-arm64-gnu@1.7.0': + optional: true + + '@node-rs/argon2-linux-arm64-musl@1.7.0': + optional: true + + '@node-rs/argon2-linux-x64-gnu@1.7.0': + optional: true + + '@node-rs/argon2-linux-x64-musl@1.7.0': + optional: true + + '@node-rs/argon2-wasm32-wasi@1.7.0': + dependencies: + '@emnapi/core': 0.45.0 + '@emnapi/runtime': 0.45.0 + '@tybys/wasm-util': 0.8.3 + memfs-browser: 3.5.10302 + optional: true + + '@node-rs/argon2-win32-arm64-msvc@1.7.0': + optional: true + + '@node-rs/argon2-win32-ia32-msvc@1.7.0': + optional: true + + '@node-rs/argon2-win32-x64-msvc@1.7.0': + optional: true + + '@node-rs/argon2@1.7.0': + optionalDependencies: + '@node-rs/argon2-android-arm-eabi': 1.7.0 + '@node-rs/argon2-android-arm64': 1.7.0 + '@node-rs/argon2-darwin-arm64': 1.7.0 + '@node-rs/argon2-darwin-x64': 1.7.0 + '@node-rs/argon2-freebsd-x64': 1.7.0 + '@node-rs/argon2-linux-arm-gnueabihf': 1.7.0 + '@node-rs/argon2-linux-arm64-gnu': 1.7.0 + '@node-rs/argon2-linux-arm64-musl': 1.7.0 + '@node-rs/argon2-linux-x64-gnu': 1.7.0 + '@node-rs/argon2-linux-x64-musl': 1.7.0 + '@node-rs/argon2-wasm32-wasi': 1.7.0 + '@node-rs/argon2-win32-arm64-msvc': 1.7.0 + '@node-rs/argon2-win32-ia32-msvc': 1.7.0 + '@node-rs/argon2-win32-x64-msvc': 1.7.0 + + '@node-rs/bcrypt-android-arm-eabi@1.9.0': + optional: true + + '@node-rs/bcrypt-android-arm64@1.9.0': + optional: true + + '@node-rs/bcrypt-darwin-arm64@1.9.0': + optional: true + + '@node-rs/bcrypt-darwin-x64@1.9.0': + optional: true + + '@node-rs/bcrypt-freebsd-x64@1.9.0': + optional: true + + '@node-rs/bcrypt-linux-arm-gnueabihf@1.9.0': + optional: true + + '@node-rs/bcrypt-linux-arm64-gnu@1.9.0': + optional: true + + '@node-rs/bcrypt-linux-arm64-musl@1.9.0': + optional: true + + '@node-rs/bcrypt-linux-x64-gnu@1.9.0': + optional: true + + '@node-rs/bcrypt-linux-x64-musl@1.9.0': + optional: true + + '@node-rs/bcrypt-wasm32-wasi@1.9.0': + dependencies: + '@emnapi/core': 0.45.0 + '@emnapi/runtime': 0.45.0 + '@tybys/wasm-util': 0.8.3 + memfs-browser: 3.5.10302 + optional: true + + '@node-rs/bcrypt-win32-arm64-msvc@1.9.0': + optional: true + + '@node-rs/bcrypt-win32-ia32-msvc@1.9.0': + optional: true + + '@node-rs/bcrypt-win32-x64-msvc@1.9.0': + optional: true + + '@node-rs/bcrypt@1.9.0': + optionalDependencies: + '@node-rs/bcrypt-android-arm-eabi': 1.9.0 + '@node-rs/bcrypt-android-arm64': 1.9.0 + '@node-rs/bcrypt-darwin-arm64': 1.9.0 + '@node-rs/bcrypt-darwin-x64': 1.9.0 + '@node-rs/bcrypt-freebsd-x64': 1.9.0 + '@node-rs/bcrypt-linux-arm-gnueabihf': 1.9.0 + '@node-rs/bcrypt-linux-arm64-gnu': 1.9.0 + '@node-rs/bcrypt-linux-arm64-musl': 1.9.0 + '@node-rs/bcrypt-linux-x64-gnu': 1.9.0 + '@node-rs/bcrypt-linux-x64-musl': 1.9.0 + '@node-rs/bcrypt-wasm32-wasi': 1.9.0 + '@node-rs/bcrypt-win32-arm64-msvc': 1.9.0 + '@node-rs/bcrypt-win32-ia32-msvc': 1.9.0 + '@node-rs/bcrypt-win32-x64-msvc': 1.9.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@paralleldrive/cuid2@2.2.2': + dependencies: + '@noble/hashes': 1.5.0 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@playwright/test@1.47.0': + dependencies: + playwright: 1.47.0 + + '@polka/url@1.0.0-next.25': {} + + '@poppinss/macroable@1.0.2': + optional: true + + '@redis/bloom@1.2.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/client@1.6.0': + dependencies: + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + yallist: 4.0.0 + + '@redis/graph@1.1.1(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/json@1.0.7(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/search@1.2.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/time-series@1.1.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@rollup/plugin-commonjs@26.0.1(rollup@4.21.3)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.3) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 10.4.5 + is-reference: 1.2.1 + magic-string: 0.30.11 + optionalDependencies: + rollup: 4.21.3 + + '@rollup/plugin-json@6.1.0(rollup@4.21.3)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.3) + optionalDependencies: + rollup: 4.21.3 + + '@rollup/plugin-node-resolve@15.2.3(rollup@4.21.3)': + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@4.21.3) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.8 + optionalDependencies: + rollup: 4.21.3 + + '@rollup/pluginutils@5.1.0(rollup@4.21.3)': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.21.3 + + '@rollup/rollup-android-arm-eabi@4.21.3': + optional: true + + '@rollup/rollup-android-arm64@4.21.3': + optional: true + + '@rollup/rollup-darwin-arm64@4.21.3': + optional: true + + '@rollup/rollup-darwin-x64@4.21.3': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.21.3': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.21.3': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.21.3': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.21.3': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.21.3': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.21.3': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.21.3': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.21.3': + optional: true + + '@rollup/rollup-linux-x64-musl@4.21.3': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.21.3': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.21.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.21.3': + optional: true + + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + optional: true + + '@sideway/formula@3.0.1': + optional: true + + '@sideway/pinpoint@2.0.0': + optional: true + + '@sinclair/typebox@0.32.35': + optional: true + + '@smithy/abort-controller@3.1.2': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/chunked-blob-reader-native@3.0.0': + dependencies: + '@smithy/util-base64': 3.0.0 + tslib: 2.7.0 + + '@smithy/chunked-blob-reader@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/config-resolver@3.0.6': + dependencies: + '@smithy/node-config-provider': 3.1.5 + '@smithy/types': 3.4.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.4 + tslib: 2.7.0 + + '@smithy/core@2.4.1': + dependencies: + '@smithy/middleware-endpoint': 3.1.1 + '@smithy/middleware-retry': 3.0.16 + '@smithy/middleware-serde': 3.0.4 + '@smithy/protocol-http': 4.1.1 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/credential-provider-imds@3.2.1': + dependencies: + '@smithy/node-config-provider': 3.1.5 + '@smithy/property-provider': 3.1.4 + '@smithy/types': 3.4.0 + '@smithy/url-parser': 3.0.4 + tslib: 2.7.0 + + '@smithy/eventstream-codec@3.1.3': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 3.4.0 + '@smithy/util-hex-encoding': 3.0.0 + tslib: 2.7.0 + + '@smithy/eventstream-serde-browser@3.0.7': + dependencies: + '@smithy/eventstream-serde-universal': 3.0.6 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/eventstream-serde-config-resolver@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/eventstream-serde-node@3.0.6': + dependencies: + '@smithy/eventstream-serde-universal': 3.0.6 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/eventstream-serde-universal@3.0.6': + dependencies: + '@smithy/eventstream-codec': 3.1.3 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/fetch-http-handler@3.2.5': + dependencies: + '@smithy/protocol-http': 4.1.1 + '@smithy/querystring-builder': 3.0.4 + '@smithy/types': 3.4.0 + '@smithy/util-base64': 3.0.0 + tslib: 2.7.0 + + '@smithy/hash-blob-browser@3.1.3': + dependencies: + '@smithy/chunked-blob-reader': 3.0.0 + '@smithy/chunked-blob-reader-native': 3.0.0 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/hash-node@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/hash-stream-node@3.1.3': + dependencies: + '@smithy/types': 3.4.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/invalid-dependency@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.7.0 + + '@smithy/is-array-buffer@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/md5-js@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/middleware-content-length@3.0.6': + dependencies: + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/middleware-endpoint@3.1.1': + dependencies: + '@smithy/middleware-serde': 3.0.4 + '@smithy/node-config-provider': 3.1.5 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + '@smithy/url-parser': 3.0.4 + '@smithy/util-middleware': 3.0.4 + tslib: 2.7.0 + + '@smithy/middleware-retry@3.0.16': + dependencies: + '@smithy/node-config-provider': 3.1.5 + '@smithy/protocol-http': 4.1.1 + '@smithy/service-error-classification': 3.0.4 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-retry': 3.0.4 + tslib: 2.7.0 + uuid: 9.0.1 + + '@smithy/middleware-serde@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/middleware-stack@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/node-config-provider@3.1.5': + dependencies: + '@smithy/property-provider': 3.1.4 + '@smithy/shared-ini-file-loader': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/node-http-handler@3.2.0': + dependencies: + '@smithy/abort-controller': 3.1.2 + '@smithy/protocol-http': 4.1.1 + '@smithy/querystring-builder': 3.0.4 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/property-provider@3.1.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/protocol-http@4.1.1': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/querystring-builder@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + '@smithy/util-uri-escape': 3.0.0 + tslib: 2.7.0 + + '@smithy/querystring-parser@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/service-error-classification@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + + '@smithy/shared-ini-file-loader@3.1.5': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/signature-v4@4.1.1': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-middleware': 3.0.4 + '@smithy/util-uri-escape': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/smithy-client@3.3.0': + dependencies: + '@smithy/middleware-endpoint': 3.1.1 + '@smithy/middleware-stack': 3.0.4 + '@smithy/protocol-http': 4.1.1 + '@smithy/types': 3.4.0 + '@smithy/util-stream': 3.1.4 + tslib: 2.7.0 + + '@smithy/types@3.4.0': + dependencies: + tslib: 2.7.0 + + '@smithy/url-parser@3.0.4': + dependencies: + '@smithy/querystring-parser': 3.0.4 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/util-base64@3.0.0': + dependencies: + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-body-length-browser@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-body-length-node@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.7.0 + + '@smithy/util-buffer-from@3.0.0': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-config-provider@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-defaults-mode-browser@3.0.16': + dependencies: + '@smithy/property-provider': 3.1.4 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + bowser: 2.11.0 + tslib: 2.7.0 + + '@smithy/util-defaults-mode-node@3.0.16': + dependencies: + '@smithy/config-resolver': 3.0.6 + '@smithy/credential-provider-imds': 3.2.1 + '@smithy/node-config-provider': 3.1.5 + '@smithy/property-provider': 3.1.4 + '@smithy/smithy-client': 3.3.0 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/util-endpoints@2.1.0': + dependencies: + '@smithy/node-config-provider': 3.1.5 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/util-hex-encoding@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-middleware@3.0.4': + dependencies: + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/util-retry@3.0.4': + dependencies: + '@smithy/service-error-classification': 3.0.4 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@smithy/util-stream@3.1.4': + dependencies: + '@smithy/fetch-http-handler': 3.2.5 + '@smithy/node-http-handler': 3.2.0 + '@smithy/types': 3.4.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-uri-escape@3.0.0': + dependencies: + tslib: 2.7.0 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.7.0 + + '@smithy/util-utf8@3.0.0': + dependencies: + '@smithy/util-buffer-from': 3.0.0 + tslib: 2.7.0 + + '@smithy/util-waiter@3.1.3': + dependencies: + '@smithy/abort-controller': 3.1.2 + '@smithy/types': 3.4.0 + tslib: 2.7.0 + + '@sodaru/yup-to-json-schema@2.0.1': + optional: true + + '@sveltejs/adapter-node@5.2.2(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))': + dependencies: + '@rollup/plugin-commonjs': 26.0.1(rollup@4.21.3) + '@rollup/plugin-json': 6.1.0(rollup@4.21.3) + '@rollup/plugin-node-resolve': 15.2.3(rollup@4.21.3) + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + rollup: 4.21.3 + + '@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4))': + dependencies: + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + '@types/cookie': 0.6.0 + cookie: 0.6.0 + devalue: 5.0.0 + esm-env: 1.0.0 + import-meta-resolve: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.11 + mrmime: 2.0.0 + sade: 1.8.1 + set-cookie-parser: 2.7.0 + sirv: 2.0.4 + svelte: 5.0.0-next.164 + tiny-glob: 0.2.9 + vite: 5.4.4(@types/node@22.5.4) + + '@sveltejs/vite-plugin-svelte-inspector@2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4))': + dependencies: + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + debug: 4.3.7 + svelte: 5.0.0-next.164 + vite: 5.4.4(@types/node@22.5.4) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte-inspector@3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4))': + dependencies: + '@sveltejs/vite-plugin-svelte': 4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + debug: 4.3.7 + svelte: 5.0.0-next.164 + vite: 5.4.4(@types/node@22.5.4) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 2.1.0(@sveltejs/vite-plugin-svelte@3.1.2(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + debug: 4.3.7 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.11 + svelte: 5.0.0-next.164 + svelte-hmr: 0.16.0(svelte@5.0.0-next.164) + vite: 5.4.4(@types/node@22.5.4) + vitefu: 0.2.5(vite@5.4.4(@types/node@22.5.4)) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 3.0.0-next.3(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + debug: 4.3.7 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.11 + svelte: 5.0.0-next.164 + vite: 5.4.4(@types/node@22.5.4) + vitefu: 1.0.2(vite@5.4.4(@types/node@22.5.4)) + transitivePeerDependencies: + - supports-color + + '@swc/helpers@0.5.13': + dependencies: + tslib: 2.7.0 + + '@tailwindcss/typography@0.5.15(tailwindcss@3.4.11)': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.4.11 + + '@tybys/wasm-util@0.8.3': + dependencies: + tslib: 2.7.0 + optional: true + + '@types/cookie@0.6.0': {} + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + + '@types/estree@1.0.5': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@22.5.4': + dependencies: + undici-types: 6.19.8 + + '@types/resolve@1.20.2': {} + + '@types/validator@13.12.1': + optional: true + + '@typescript-eslint/eslint-plugin@8.5.0(@typescript-eslint/parser@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2))(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)': + dependencies: + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.5.0 + '@typescript-eslint/type-utils': 8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/utils': 8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.5.0 + eslint: 9.10.0(jiti@1.21.6) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.5.0 + '@typescript-eslint/types': 8.5.0 + '@typescript-eslint/typescript-estree': 8.5.0(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.5.0 + debug: 4.3.7 + eslint: 9.10.0(jiti@1.21.6) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.5.0': + dependencies: + '@typescript-eslint/types': 8.5.0 + '@typescript-eslint/visitor-keys': 8.5.0 + + '@typescript-eslint/type-utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)': + dependencies: + '@typescript-eslint/typescript-estree': 8.5.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2) + debug: 4.3.7 + ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - eslint + - supports-color + + '@typescript-eslint/types@8.5.0': {} + + '@typescript-eslint/typescript-estree@8.5.0(typescript@5.6.2)': + dependencies: + '@typescript-eslint/types': 8.5.0 + '@typescript-eslint/visitor-keys': 8.5.0 + debug: 4.3.7 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.6.2) + optionalDependencies: + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.5.0(eslint@9.10.0(jiti@1.21.6))(typescript@5.6.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.10.0(jiti@1.21.6)) + '@typescript-eslint/scope-manager': 8.5.0 + '@typescript-eslint/types': 8.5.0 + '@typescript-eslint/typescript-estree': 8.5.0(typescript@5.6.2) + eslint: 9.10.0(jiti@1.21.6) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@8.5.0': + dependencies: + '@typescript-eslint/types': 8.5.0 + eslint-visitor-keys: 3.4.3 + + '@vinejs/compiler@2.5.0': + optional: true + + '@vinejs/vine@1.8.0': + dependencies: + '@poppinss/macroable': 1.0.2 + '@types/validator': 13.12.1 + '@vinejs/compiler': 2.5.0 + camelcase: 8.0.0 + dayjs: 1.11.13 + dlv: 1.1.3 + normalize-url: 8.0.1 + validator: 13.12.0 + optional: true + + '@vitest/expect@2.1.0': + dependencies: + '@vitest/spy': 2.1.0 + '@vitest/utils': 2.1.0 + chai: 5.1.1 + tinyrainbow: 1.2.0 + + '@vitest/mocker@2.1.0(@vitest/spy@2.1.0)(vite@5.4.4(@types/node@22.5.4))': + dependencies: + '@vitest/spy': 2.1.0 + estree-walker: 3.0.3 + magic-string: 0.30.11 + optionalDependencies: + vite: 5.4.4(@types/node@22.5.4) + + '@vitest/pretty-format@2.1.0': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.1.0': + dependencies: + '@vitest/utils': 2.1.0 + pathe: 1.1.2 + + '@vitest/snapshot@2.1.0': + dependencies: + '@vitest/pretty-format': 2.1.0 + magic-string: 0.30.11 + pathe: 1.1.2 + + '@vitest/spy@2.1.0': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.1.0': + dependencies: + '@vitest/pretty-format': 2.1.0 + loupe: 3.1.1 + tinyrainbow: 1.2.0 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn-typescript@1.4.13(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn@8.12.1: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arctic@1.9.2: + dependencies: + oslo: 1.2.0 + + arg@5.0.2: {} + + argparse@2.0.1: {} + + aria-query@5.3.1: {} + + arktype@2.0.0-beta.0: + dependencies: + '@ark/schema': 0.2.0 + '@ark/util': 0.1.0 + optional: true + + array-flatten@1.1.1: {} + + assertion-error@2.0.1: {} + + autoprefixer@10.4.20(postcss@8.4.45): + dependencies: + browserslist: 4.23.3 + caniuse-lite: 1.0.30001660 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.0 + postcss: 8.4.45 + postcss-value-parser: 4.2.0 + + axobject-query@4.1.0: {} + + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + bits-ui@0.21.13(svelte@5.0.0-next.164): + dependencies: + '@internationalized/date': 3.5.5 + '@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.164) + nanoid: 5.0.7 + svelte: 5.0.0-next.164 + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bowser@2.11.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.23.3: + dependencies: + caniuse-lite: 1.0.30001660 + electron-to-chromium: 1.5.21 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.3) + + buffer-from@1.1.2: {} + + builtin-modules@3.3.0: {} + + bullmq@5.13.0: + dependencies: + cron-parser: 4.9.0 + ioredis: 5.4.1 + msgpackr: 1.11.0 + node-abort-controller: 3.1.1 + semver: 7.6.3 + tslib: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + + bytes@3.1.2: {} + + cac@6.7.14: {} + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + camelcase-css@2.0.1: {} + + camelcase@8.0.0: + optional: true + + caniuse-lite@1.0.30001660: {} + + chai@5.1.1: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.1 + pathval: 2.0.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + check-error@2.1.1: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + clsx@2.1.1: {} + + cluster-key-slot@1.1.2: {} + + cmdk-sv@0.0.18(svelte@5.0.0-next.164): + dependencies: + bits-ui: 0.21.13(svelte@5.0.0-next.164) + nanoid: 5.0.7 + svelte: 5.0.0-next.164 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commander@4.1.1: {} + + commondir@1.0.1: {} + + concat-map@0.0.1: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-signature@1.0.6: {} + + cookie@0.6.0: {} + + cron-parser@4.9.0: + dependencies: + luxon: 3.5.0 + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + dayjs@1.11.13: + optional: true + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + denque@2.1.0: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + destroy@1.2.0: {} + + detect-libc@2.0.3: + optional: true + + devalue@5.0.0: {} + + didyoumean@1.2.2: {} + + dlv@1.1.3: {} + + dotenv-cli@7.4.2: + dependencies: + cross-spawn: 7.0.3 + dotenv: 16.4.5 + dotenv-expand: 10.0.0 + minimist: 1.2.8 + + dotenv-expand@10.0.0: {} + + dotenv@16.4.5: {} + + drizzle-kit@0.26.2: + dependencies: + '@drizzle-team/brocli': 0.10.1 + '@esbuild-kit/esm-loader': 2.6.5 + esbuild: 0.19.12 + esbuild-register: 3.6.0(esbuild@0.19.12) + transitivePeerDependencies: + - supports-color + + drizzle-orm@0.35.1(pg@8.12.0)(postgres@3.4.4)(react@18.3.1): + optionalDependencies: + pg: 8.12.0 + postgres: 3.4.4 + react: 18.3.1 + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.21: {} + + embla-carousel-reactive-utils@8.2.1(embla-carousel@8.2.1): + dependencies: + embla-carousel: 8.2.1 + + embla-carousel-svelte@8.2.1(svelte@5.0.0-next.164): + dependencies: + embla-carousel: 8.2.1 + embla-carousel-reactive-utils: 8.2.1(embla-carousel@8.2.1) + svelte: 5.0.0-next.164 + + embla-carousel@8.2.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + esbuild-register@3.6.0(esbuild@0.19.12): + dependencies: + debug: 4.3.7 + esbuild: 0.19.12 + transitivePeerDependencies: + - supports-color + + esbuild-runner@2.2.2(esbuild@0.23.1): + dependencies: + esbuild: 0.23.1 + source-map-support: 0.5.21 + tslib: 2.4.0 + optional: true + + esbuild@0.18.20: + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + + esbuild@0.19.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + optional: true + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + eslint-compat-utils@0.5.1(eslint@9.10.0(jiti@1.21.6)): + dependencies: + eslint: 9.10.0(jiti@1.21.6) + semver: 7.6.3 + + eslint-config-prettier@9.1.0(eslint@9.10.0(jiti@1.21.6)): + dependencies: + eslint: 9.10.0(jiti@1.21.6) + + eslint-plugin-svelte@2.43.0(eslint@9.10.0(jiti@1.21.6))(svelte@5.0.0-next.164): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.10.0(jiti@1.21.6)) + '@jridgewell/sourcemap-codec': 1.5.0 + eslint: 9.10.0(jiti@1.21.6) + eslint-compat-utils: 0.5.1(eslint@9.10.0(jiti@1.21.6)) + esutils: 2.0.3 + known-css-properties: 0.34.0 + postcss: 8.4.45 + postcss-load-config: 3.1.4(postcss@8.4.45) + postcss-safe-parser: 6.0.0(postcss@8.4.45) + postcss-selector-parser: 6.1.2 + semver: 7.6.3 + svelte-eslint-parser: 0.41.0(svelte@5.0.0-next.164) + optionalDependencies: + svelte: 5.0.0-next.164 + transitivePeerDependencies: + - ts-node + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@8.0.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.0.0: {} + + eslint@9.10.0(jiti@1.21.6): + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.10.0(jiti@1.21.6)) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.18.0 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.10.0 + '@eslint/plugin-kit': 0.1.0 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.7 + escape-string-regexp: 4.0.0 + eslint-scope: 8.0.2 + eslint-visitor-keys: 4.0.0 + espree: 10.1.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + optionalDependencies: + jiti: 1.21.6 + transitivePeerDependencies: + - supports-color + + esm-env@1.0.0: {} + + espree@10.1.0: + dependencies: + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 4.0.0 + + espree@9.6.1: + dependencies: + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 3.4.3 + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrap@1.2.2: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@types/estree': 1.0.5 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + express-rate-limit@7.4.0(express@4.21.0): + dependencies: + express: 4.21.0 + + express@4.21.0: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.10 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-xml-parser@4.4.1: + dependencies: + strnum: 1.0.5 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fdir@6.3.0: {} + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + + flatted@3.3.1: {} + + focus-trap@7.6.0: + dependencies: + tabbable: 6.2.0 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + formsnap@1.0.1(svelte@5.0.0-next.164)(sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)): + dependencies: + nanoid: 5.0.7 + svelte: 5.0.0-next.164 + sveltekit-superforms: 2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164) + + forwarded@0.2.0: {} + + fraction.js@4.3.7: {} + + fresh@0.5.2: {} + + fs-monkey@1.0.6: + optional: true + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + generic-pool@3.9.0: {} + + get-func-name@2.0.2: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-tsconfig@4.8.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 + + globals@14.0.0: {} + + globalyzer@0.1.0: {} + + globrex@0.1.2: {} + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + graphemer@1.4.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hono-rate-limiter@0.4.0(hono@4.6.1): + dependencies: + hono: 4.6.1 + + hono@4.6.1: {} + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.1.0: {} + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + ioredis@5.4.1: + dependencies: + '@ioredis/commands': 1.2.0 + cluster-key-slot: 1.1.2 + debug: 4.3.7 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + ipaddr.js@1.9.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-module@1.0.0: {} + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.5 + + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.6: {} + + joi@17.13.3: + 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 + optional: true + + js-tokens@4.0.0: + optional: true + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.25.6 + ts-algebra: 2.0.0 + optional: true + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + jsonpath-plus@7.2.0: {} + + just-clone@6.2.0: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kleur@4.1.5: {} + + known-css-properties@0.34.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + + lines-and-columns@1.2.4: {} + + locate-character@3.0.0: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.castarray@4.4.0: {} + + lodash.defaults@4.2.0: {} + + lodash.isarguments@3.1.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.merge@4.6.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + optional: true + + loupe@3.1.1: + dependencies: + get-func-name: 2.0.2 + + lru-cache@10.4.3: {} + + lucia@3.2.0: + dependencies: + oslo: 1.2.0 + + lucide-svelte@0.441.0(svelte@5.0.0-next.164): + dependencies: + svelte: 5.0.0-next.164 + + luxon@3.5.0: {} + + magic-string@0.30.11: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + media-typer@0.3.0: {} + + memfs-browser@3.5.10302: + dependencies: + memfs: 3.5.3 + optional: true + + memfs@3.5.3: + dependencies: + fs-monkey: 1.0.6 + optional: true + + memoize-weak@1.0.2: {} + + merge-descriptors@1.0.3: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mode-watcher@0.4.1(svelte@5.0.0-next.164): + dependencies: + svelte: 5.0.0-next.164 + + mri@1.2.0: {} + + mrmime@2.0.0: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + msgpackr-extract@3.0.3: + dependencies: + node-gyp-build-optional-packages: 5.2.2 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + optional: true + + msgpackr@1.11.0: + optionalDependencies: + msgpackr-extract: 3.0.3 + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.7: {} + + nanoid@5.0.7: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + node-abort-controller@3.1.1: {} + + node-gyp-build-optional-packages@5.2.2: + dependencies: + detect-libc: 2.0.3 + optional: true + + node-releases@2.0.18: {} + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + normalize-url@8.0.1: + optional: true + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + oslo@1.2.0: + dependencies: + '@node-rs/argon2': 1.7.0 + '@node-rs/bcrypt': 1.9.0 + + oslo@1.2.1: + dependencies: + '@node-rs/argon2': 1.7.0 + '@node-rs/bcrypt': 1.9.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + package-json-from-dist@1.0.0: {} + + paneforge@0.0.5(svelte@5.0.0-next.164): + dependencies: + nanoid: 5.0.7 + svelte: 5.0.0-next.164 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-to-regexp@0.1.10: {} + + pathe@1.1.2: {} + + pathval@2.0.0: {} + + pg-cloudflare@1.1.1: + optional: true + + pg-connection-string@2.6.4: {} + + pg-int8@1.0.1: {} + + pg-pool@3.6.2(pg@8.12.0): + dependencies: + pg: 8.12.0 + + pg-protocol@1.6.1: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + pg@8.12.0: + dependencies: + pg-connection-string: 2.6.4 + pg-pool: 3.6.2(pg@8.12.0) + pg-protocol: 1.6.1 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.1.1 + + pgpass@1.0.5: + dependencies: + split2: 4.2.0 + + picocolors@1.1.0: {} + + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pirates@4.0.6: {} + + playwright-core@1.47.0: {} + + playwright@1.47.0: + dependencies: + playwright-core: 1.47.0 + optionalDependencies: + fsevents: 2.3.2 + + postcss-import@15.1.0(postcss@8.4.45): + dependencies: + postcss: 8.4.45 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.45): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.45 + + postcss-load-config@3.1.4(postcss@8.4.45): + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + optionalDependencies: + postcss: 8.4.45 + + postcss-load-config@4.0.2(postcss@8.4.45): + dependencies: + lilconfig: 3.1.2 + yaml: 2.5.1 + optionalDependencies: + postcss: 8.4.45 + + postcss-nested@6.2.0(postcss@8.4.45): + dependencies: + postcss: 8.4.45 + postcss-selector-parser: 6.1.2 + + postcss-safe-parser@6.0.0(postcss@8.4.45): + dependencies: + postcss: 8.4.45 + + postcss-scss@4.0.9(postcss@8.4.45): + dependencies: + postcss: 8.4.45 + + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.45: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + + postgres-array@2.0.0: {} + + postgres-bytea@1.0.0: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + postgres@3.4.4: {} + + prelude-ls@1.2.1: {} + + prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@5.0.0-next.164): + dependencies: + prettier: 3.3.3 + svelte: 5.0.0-next.164 + + prettier-plugin-tailwindcss@0.6.6(prettier-plugin-svelte@3.2.6(prettier@3.3.3)(svelte@5.0.0-next.164))(prettier@3.3.3): + dependencies: + prettier: 3.3.3 + optionalDependencies: + prettier-plugin-svelte: 3.2.6(prettier@3.3.3)(svelte@5.0.0-next.164) + + prettier@3.3.3: {} + + property-expr@2.0.6: + optional: true + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + punycode@2.3.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.0.6 + + queue-microtask@1.2.3: {} + + range-parser@1.2.1: {} + + rate-limit-redis@4.2.0(express-rate-limit@7.4.0(express@4.21.0)): + dependencies: + express-rate-limit: 7.4.0(express@4.21.0) + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + optional: true + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + redis-errors@1.2.0: {} + + redis-om@0.4.6: + dependencies: + jsonpath-plus: 7.2.0 + just-clone: 6.2.0 + redis: 4.7.0 + ulid: 2.3.0 + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + + redis@4.7.0: + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.6.0) + '@redis/client': 1.6.0 + '@redis/graph': 1.1.1(@redis/client@1.6.0) + '@redis/json': 1.0.7(@redis/client@1.6.0) + '@redis/search': 1.2.0(@redis/client@1.6.0) + '@redis/time-series': 1.1.0(@redis/client@1.6.0) + + reflect-metadata@0.2.2: {} + + regenerator-runtime@0.14.1: + optional: true + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rollup@4.21.3: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.21.3 + '@rollup/rollup-android-arm64': 4.21.3 + '@rollup/rollup-darwin-arm64': 4.21.3 + '@rollup/rollup-darwin-x64': 4.21.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.3 + '@rollup/rollup-linux-arm-musleabihf': 4.21.3 + '@rollup/rollup-linux-arm64-gnu': 4.21.3 + '@rollup/rollup-linux-arm64-musl': 4.21.3 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.3 + '@rollup/rollup-linux-riscv64-gnu': 4.21.3 + '@rollup/rollup-linux-s390x-gnu': 4.21.3 + '@rollup/rollup-linux-x64-gnu': 4.21.3 + '@rollup/rollup-linux-x64-musl': 4.21.3 + '@rollup/rollup-win32-arm64-msvc': 4.21.3 + '@rollup/rollup-win32-ia32-msvc': 4.21.3 + '@rollup/rollup-win32-x64-msvc': 4.21.3 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + semver@7.6.3: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-cookie-parser@2.7.0: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.25 + mrmime: 2.0.0 + totalist: 3.0.1 + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + split2@4.2.0: {} + + stackback@0.0.2: {} + + standard-as-callback@2.1.0: {} + + statuses@2.0.1: {} + + std-env@3.7.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-json-comments@3.1.1: {} + + strnum@1.0.5: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + superstruct@2.0.2: + optional: true + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svelte-check@4.0.2(svelte@5.0.0-next.164)(typescript@5.6.2): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + chokidar: 3.6.0 + fdir: 6.3.0 + picocolors: 1.1.0 + sade: 1.8.1 + svelte: 5.0.0-next.164 + typescript: 5.6.2 + transitivePeerDependencies: + - picomatch + + svelte-dnd-action@0.9.50(svelte@5.0.0-next.164): + dependencies: + svelte: 5.0.0-next.164 + + svelte-eslint-parser@0.41.0(svelte@5.0.0-next.164): + dependencies: + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + postcss: 8.4.45 + postcss-scss: 4.0.9(postcss@8.4.45) + optionalDependencies: + svelte: 5.0.0-next.164 + + svelte-hmr@0.16.0(svelte@5.0.0-next.164): + dependencies: + svelte: 5.0.0-next.164 + + svelte-sonner@0.3.28(svelte@5.0.0-next.164): + dependencies: + svelte: 5.0.0-next.164 + + svelte@5.0.0-next.164: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.5.0 + '@types/estree': 1.0.5 + acorn: 8.12.1 + acorn-typescript: 1.4.13(acorn@8.12.1) + aria-query: 5.3.1 + axobject-query: 4.1.0 + esm-env: 1.0.0 + esrap: 1.2.2 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.11 + zimmerframe: 1.1.2 + + sveltekit-search-params@3.0.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)): + dependencies: + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + svelte: 5.0.0-next.164 + transitivePeerDependencies: + - supports-color + - vite + + sveltekit-superforms@2.17.0(@sveltejs/kit@2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164): + dependencies: + '@sveltejs/kit': 2.5.26(@sveltejs/vite-plugin-svelte@4.0.0-next.7(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)))(svelte@5.0.0-next.164)(vite@5.4.4(@types/node@22.5.4)) + devalue: 5.0.0 + just-clone: 6.2.0 + memoize-weak: 1.0.2 + svelte: 5.0.0-next.164 + ts-deepmerge: 7.0.1 + optionalDependencies: + '@exodus/schemasafe': 1.3.0 + '@gcornut/valibot-json-schema': 0.31.0 + '@sinclair/typebox': 0.32.35 + '@sodaru/yup-to-json-schema': 2.0.1 + '@vinejs/vine': 1.8.0 + arktype: 2.0.0-beta.0 + joi: 17.13.3 + json-schema-to-ts: 3.1.1 + superstruct: 2.0.2 + valibot: 0.35.0 + yup: 1.4.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + + tabbable@6.2.0: {} + + tailwind-merge@2.5.2: {} + + tailwind-variants@0.2.1(tailwindcss@3.4.11): + dependencies: + tailwind-merge: 2.5.2 + tailwindcss: 3.4.11 + + tailwindcss@3.4.11: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.0 + postcss: 8.4.45 + postcss-import: 15.1.0(postcss@8.4.45) + postcss-js: 4.0.1(postcss@8.4.45) + postcss-load-config: 4.0.2(postcss@8.4.45) + postcss-nested: 6.2.0(postcss@8.4.45) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + text-table@0.2.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tiny-case@1.0.3: + optional: true + + tiny-glob@0.2.9: + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + + tinybench@2.9.0: {} + + tinyexec@0.3.0: {} + + tinypool@1.0.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + toposort@2.0.2: + optional: true + + totalist@3.0.1: {} + + ts-algebra@2.0.0: + optional: true + + ts-api-utils@1.3.0(typescript@5.6.2): + dependencies: + typescript: 5.6.2 + + ts-deepmerge@7.0.1: {} + + ts-interface-checker@0.1.13: {} + + tslib@1.14.1: {} + + tslib@2.4.0: + optional: true + + tslib@2.7.0: {} + + tsyringe@4.8.0: + dependencies: + tslib: 1.14.1 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@2.19.0: + optional: true + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typescript@5.6.2: {} + + ulid@2.3.0: {} + + undici-types@6.19.8: {} + + unpipe@1.0.0: {} + + update-browserslist-db@1.1.0(browserslist@4.23.3): + dependencies: + browserslist: 4.23.3 + escalade: 3.2.0 + picocolors: 1.1.0 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + uuid@9.0.1: {} + + valibot@0.31.1: + optional: true + + valibot@0.35.0: + optional: true + + validator@13.12.0: + optional: true + + vary@1.1.2: {} + + vaul-svelte@0.3.2(svelte@5.0.0-next.164): + dependencies: + bits-ui: 0.21.13(svelte@5.0.0-next.164) + svelte: 5.0.0-next.164 + + vite-node@2.1.0(@types/node@22.5.4): + dependencies: + cac: 6.7.14 + debug: 4.3.7 + pathe: 1.1.2 + vite: 5.4.4(@types/node@22.5.4) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.4(@types/node@22.5.4): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.45 + rollup: 4.21.3 + optionalDependencies: + '@types/node': 22.5.4 + fsevents: 2.3.3 + + vitefu@0.2.5(vite@5.4.4(@types/node@22.5.4)): + optionalDependencies: + vite: 5.4.4(@types/node@22.5.4) + + vitefu@1.0.2(vite@5.4.4(@types/node@22.5.4)): + optionalDependencies: + vite: 5.4.4(@types/node@22.5.4) + + vitest@2.1.0(@types/node@22.5.4): + dependencies: + '@vitest/expect': 2.1.0 + '@vitest/mocker': 2.1.0(@vitest/spy@2.1.0)(vite@5.4.4(@types/node@22.5.4)) + '@vitest/pretty-format': 2.1.0 + '@vitest/runner': 2.1.0 + '@vitest/snapshot': 2.1.0 + '@vitest/spy': 2.1.0 + '@vitest/utils': 2.1.0 + chai: 5.1.1 + debug: 4.3.7 + magic-string: 0.30.11 + pathe: 1.1.2 + std-env: 3.7.0 + tinybench: 2.9.0 + tinyexec: 0.3.0 + tinypool: 1.0.1 + tinyrainbow: 1.2.0 + vite: 5.4.4(@types/node@22.5.4) + vite-node: 2.1.0(@types/node@22.5.4) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.5.4 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + xtend@4.0.2: {} + + yallist@4.0.0: {} + + yaml@1.10.2: {} + + yaml@2.5.1: {} + + yocto-queue@0.1.0: {} + + yup@1.4.0: + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + optional: true + + zimmerframe@1.1.2: {} + + zod-to-json-schema@3.23.3(zod@3.23.8): + dependencies: + zod: 3.23.8 + optional: true + + zod@3.23.8: {} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..0f77216 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/render.yaml b/render.yaml new file mode 100644 index 0000000..c032a45 --- /dev/null +++ b/render.yaml @@ -0,0 +1,101 @@ +services: + # Web + - type: web + name: web + runtime: node + region: oregon # optional (defaults to oregon) + plan: starter # optional (defaults to starter instance type) + branch: main # optional (defaults to master) + buildCommand: npm install --force && npm run build + startCommand: npm run db:migrate && node build/index.js + healthCheckPath: / + envVars: + - key: STORAGE_API_SECRET_KEY + fromService: + name: minio-server + type: web + property: MINIO_ROOT_PASSWORD + - key: STORAGE_ACCESS_KEY + fromService: + name: minio-server + type: web + property: MINIO_ROOT_USER + - key: STORAGE_API_URL + fromService: + name: minio-server + type: web + property: connectionString + - key: DATABASE_URL + fromDatabase: + name: tofustack + property: connectionString + - key: REDIS_URL + fromService: + name: redis + type: redis + property: connectionString + - key: PUBLIC_ORIGIN + fromService: + name: web + type: web + property: host + # Redis + - type: redis + name: redis + ipAllowList: [] # Only allow internal connections + + # MinIO Server + - type: web + name: minio-server + healthCheckPath: /minio/health/liveweb + runtime: image + image: + url: docker.io/minio/minio:latest + dockerCommand: minio server /data --address $HOST:$PORT --console-address $HOST:$CONSOLE_PORT + # Use the following 'dockerCommand' if removing the 'minio-console' + # web service + # dockerCommand: minio server /data --address $HOST:$PORT + autoDeploy: false + disk: + name: data + mountPath: /data + envVars: + - key: MINIO_ROOT_USER + generateValue: true + - key: MINIO_ROOT_PASSWORD + generateValue: true + - key: HOST + value: "0.0.0.0" + - key: PORT + value: 9000 + - key: CONSOLE_PORT + value: 9090 + # Uncomment the following key/value pair if you are removing the + # 'minio-console' web service + # - key: MINIO_BROWSER + # value: "off" + # MinIO Console + - type: web + name: minio-console + runtime: docker + dockerContext: / + dockerfilePath: ./Dockerfile.minio + autoDeploy: false + envVars: + - key: PORT + value: 10000 + - key: MINIO_HOST + fromService: + name: minio-server + type: web + property: host + - key: MINIO_CONSOLE_PORT + fromService: + name: minio-server + type: web + envVarKey: CONSOLE_PORT + +databases: + - name: db + databaseName: tofustack + ipAllowList: [] diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..6ff7062 --- /dev/null +++ b/src/app.css @@ -0,0 +1,78 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 72.2% 50.6%; + --destructive-foreground: 210 40% 98%; + + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --ring: hsl(212.7,26.8%,83.9); + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file diff --git a/src/app.d.ts b/src/app.d.ts new file mode 100644 index 0000000..0b04506 --- /dev/null +++ b/src/app.d.ts @@ -0,0 +1,30 @@ +import { ApiClient } from '$lib/server/api'; +import type { User } from 'lucia'; +import { parseApiResponse } from '$lib/utils/api' +import type { Security } from '$lib/utils/security'; + +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + interface Locals { + api: ApiClient['api']; + parseApiResponse: typeof parseApiResponse; + getAuthedUser: () => Promise | null>; + getAuthedUserOrThrow: (redirectTo: string) => Promise>; + } + + // interface PageData {} + // interface PageState {} + // interface Platform {} + namespace Superforms { + type Message = { + type: 'error' | 'success', + text: string + } + } + } +} + +export { }; diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..77a5ff5 --- /dev/null +++ b/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/src/hooks.server.ts b/src/hooks.server.ts new file mode 100644 index 0000000..c0de2e1 --- /dev/null +++ b/src/hooks.server.ts @@ -0,0 +1,42 @@ +import 'reflect-metadata' +import { hc } from 'hono/client'; +import { redirect, type Handle } from '@sveltejs/kit'; +import { sequence } from '@sveltejs/kit/hooks'; +import type { ApiRoutes } from '$lib/server/api'; +import { parseApiResponse } from '$lib/utils/api'; +import { StatusCodes } from '$lib/constants/status-codes'; + +const apiClient: Handle = async ({ event, resolve }) => { + /* ------------------------------ Register api ------------------------------ */ + const { api } = hc('/', { + fetch: event.fetch, + headers: { + 'x-forwarded-for': event.getClientAddress(), + host: event.request.headers.get('host') || '' + } + }); + + /* ----------------------------- Auth functions ----------------------------- */ + async function getAuthedUser() { + const { data } = await api.iam.me.$get().then(parseApiResponse) + return data && data.user; + } + + async function getAuthedUserOrThrow(redirectTo = '/') { + const { data } = await api.iam.me.$get().then(parseApiResponse); + if (!data || !data.user) throw redirect(StatusCodes.TEMPORARY_REDIRECT, redirectTo); + return data?.user; + } + + /* ------------------------------ Set contexts ------------------------------ */ + event.locals.api = api; + event.locals.parseApiResponse = parseApiResponse; + event.locals.getAuthedUser = getAuthedUser; + event.locals.getAuthedUserOrThrow = getAuthedUserOrThrow; + + /* ----------------------------- Return response ---------------------------- */ + const response = await resolve(event); + return response; +}; + +export const handle = sequence(apiClient); diff --git a/src/index.test.ts b/src/index.test.ts new file mode 100644 index 0000000..e07cbbd --- /dev/null +++ b/src/index.test.ts @@ -0,0 +1,7 @@ +import { describe, it, expect } from 'vitest'; + +describe('sum test', () => { + it('adds 1 + 2 to equal 3', () => { + expect(1 + 2).toBe(3); + }); +}); diff --git a/src/lib/components/container.svelte b/src/lib/components/container.svelte new file mode 100644 index 0000000..b62e84a --- /dev/null +++ b/src/lib/components/container.svelte @@ -0,0 +1,15 @@ + + +
+ {@render children()} +
diff --git a/src/lib/components/pin-input.svelte b/src/lib/components/pin-input.svelte new file mode 100644 index 0000000..0c4b84b --- /dev/null +++ b/src/lib/components/pin-input.svelte @@ -0,0 +1,32 @@ + + + + {#each inputs as _} + + {/each} + + 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..eca3fe5 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion-content.svelte @@ -0,0 +1,25 @@ + + + +
+ +
+
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..85ef052 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion-item.svelte @@ -0,0 +1,14 @@ + + + + + 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..df00d47 --- /dev/null +++ b/src/lib/components/ui/accordion/accordion-trigger.svelte @@ -0,0 +1,26 @@ + + + + svg]:rotate-180", + className + )} + {...$$restProps} + on:click + > + + + + diff --git a/src/lib/components/ui/accordion/index.ts b/src/lib/components/ui/accordion/index.ts new file mode 100644 index 0000000..ed49213 --- /dev/null +++ b/src/lib/components/ui/accordion/index.ts @@ -0,0 +1,17 @@ +import { Accordion as AccordionPrimitive } from "bits-ui"; +import Content from "./accordion-content.svelte"; +import Item from "./accordion-item.svelte"; +import Trigger from "./accordion-trigger.svelte"; +const Root = AccordionPrimitive.Root; + +export { + Root, + Content, + Item, + Trigger, + // + Root as Accordion, + Content as AccordionContent, + Item as AccordionItem, + Trigger as AccordionTrigger, +}; 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..4a275f6 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte @@ -0,0 +1,21 @@ + + + + + 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..8343b72 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte @@ -0,0 +1,21 @@ + + + + + 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..5b18b64 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte @@ -0,0 +1,28 @@ + + + + + + + + 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..9967bb0 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte @@ -0,0 +1,16 @@ + + + + + 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..0b21f15 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte @@ -0,0 +1,16 @@ + + +
+ +
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..482977e --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte @@ -0,0 +1,13 @@ + + +
+ +
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..4795e83 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte @@ -0,0 +1,21 @@ + + + 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..e227219 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte @@ -0,0 +1,9 @@ + + + + + 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..a110e1f --- /dev/null +++ b/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte @@ -0,0 +1,14 @@ + + + + + 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..be56dd7 --- /dev/null +++ b/src/lib/components/ui/alert-dialog/index.ts @@ -0,0 +1,40 @@ +import { AlertDialog as AlertDialogPrimitive } from "bits-ui"; + +import Title from "./alert-dialog-title.svelte"; +import Action from "./alert-dialog-action.svelte"; +import Cancel from "./alert-dialog-cancel.svelte"; +import Portal from "./alert-dialog-portal.svelte"; +import Footer from "./alert-dialog-footer.svelte"; +import Header from "./alert-dialog-header.svelte"; +import Overlay from "./alert-dialog-overlay.svelte"; +import Content from "./alert-dialog-content.svelte"; +import Description from "./alert-dialog-description.svelte"; + +const Root = AlertDialogPrimitive.Root; +const Trigger = AlertDialogPrimitive.Trigger; + +export { + Root, + Title, + Action, + Cancel, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + // + Root as AlertDialog, + Title as AlertDialogTitle, + Action as AlertDialogAction, + Cancel as AlertDialogCancel, + Portal as AlertDialogPortal, + Footer as AlertDialogFooter, + Header as AlertDialogHeader, + Trigger as AlertDialogTrigger, + Overlay as AlertDialogOverlay, + Content as AlertDialogContent, + Description as AlertDialogDescription, +}; 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..aa9ed03 --- /dev/null +++ b/src/lib/components/ui/alert/alert-description.svelte @@ -0,0 +1,13 @@ + + +
+ +
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..1482e6e --- /dev/null +++ b/src/lib/components/ui/alert/alert-title.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/ui/alert/alert.svelte b/src/lib/components/ui/alert/alert.svelte new file mode 100644 index 0000000..b4c9536 --- /dev/null +++ b/src/lib/components/ui/alert/alert.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/alert/index.ts b/src/lib/components/ui/alert/index.ts new file mode 100644 index 0000000..c21bc1e --- /dev/null +++ b/src/lib/components/ui/alert/index.ts @@ -0,0 +1,33 @@ +import { type VariantProps, tv } from "tailwind-variants"; + +import Root from "./alert.svelte"; +import Description from "./alert-description.svelte"; +import Title from "./alert-title.svelte"; + +export const alertVariants = tv({ + base: "relative w-full rounded-lg border p-4 [&:has(svg)]:pl-11 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, +}); + +export type Variant = VariantProps["variant"]; +export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; + +export { + Root, + Description, + Title, + // + Root as Alert, + Description as AlertDescription, + Title as AlertTitle, +}; 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..b3da1f3 --- /dev/null +++ b/src/lib/components/ui/aspect-ratio/aspect-ratio.svelte @@ -0,0 +1,11 @@ + + + + + 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..985c75f --- /dev/null +++ b/src/lib/components/ui/aspect-ratio/index.ts @@ -0,0 +1,3 @@ +import Root from "./aspect-ratio.svelte"; + +export { Root, Root as AspectRatio }; 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..6dece44 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-fallback.svelte @@ -0,0 +1,16 @@ + + + + + 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..32ca45f --- /dev/null +++ b/src/lib/components/ui/avatar/avatar-image.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/lib/components/ui/avatar/avatar.svelte b/src/lib/components/ui/avatar/avatar.svelte new file mode 100644 index 0000000..3f72721 --- /dev/null +++ b/src/lib/components/ui/avatar/avatar.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/src/lib/components/ui/avatar/index.ts b/src/lib/components/ui/avatar/index.ts new file mode 100644 index 0000000..d06457b --- /dev/null +++ b/src/lib/components/ui/avatar/index.ts @@ -0,0 +1,13 @@ +import Root from "./avatar.svelte"; +import Image from "./avatar-image.svelte"; +import Fallback from "./avatar-fallback.svelte"; + +export { + Root, + Image, + Fallback, + // + Root as Avatar, + Image as AvatarImage, + Fallback as AvatarFallback, +}; diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte new file mode 100644 index 0000000..f581743 --- /dev/null +++ b/src/lib/components/ui/badge/badge.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts new file mode 100644 index 0000000..e907993 --- /dev/null +++ b/src/lib/components/ui/badge/index.ts @@ -0,0 +1,21 @@ +import { type VariantProps, tv } from "tailwind-variants"; +export { default as Badge } from "./badge.svelte"; + +export const badgeVariants = tv({ + base: "inline-flex select-none items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + variants: { + variant: { + default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, +}); + +export type Variant = VariantProps["variant"]; 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..c010b2e --- /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..d2b5e9c --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte @@ -0,0 +1,16 @@ + + +
  • + +
  • 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..4160a9e --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte @@ -0,0 +1,31 @@ + + +{#if asChild} + +{:else} + + + +{/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..43609cc --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte @@ -0,0 +1,23 @@ + + +
      + +
    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..9fa82c2 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte @@ -0,0 +1,23 @@ + + + + + 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..5f2dedf --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte @@ -0,0 +1,25 @@ + + + diff --git a/src/lib/components/ui/breadcrumb/breadcrumb.svelte b/src/lib/components/ui/breadcrumb/breadcrumb.svelte new file mode 100644 index 0000000..104f8b0 --- /dev/null +++ b/src/lib/components/ui/breadcrumb/breadcrumb.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/lib/components/ui/breadcrumb/index.ts b/src/lib/components/ui/breadcrumb/index.ts new file mode 100644 index 0000000..dc914ec --- /dev/null +++ b/src/lib/components/ui/breadcrumb/index.ts @@ -0,0 +1,25 @@ +import Root from "./breadcrumb.svelte"; +import Ellipsis from "./breadcrumb-ellipsis.svelte"; +import Item from "./breadcrumb-item.svelte"; +import Separator from "./breadcrumb-separator.svelte"; +import Link from "./breadcrumb-link.svelte"; +import List from "./breadcrumb-list.svelte"; +import Page from "./breadcrumb-page.svelte"; + +export { + Root, + Ellipsis, + Item, + Separator, + Link, + List, + Page, + // + Root as Breadcrumb, + Ellipsis as BreadcrumbEllipsis, + Item as BreadcrumbItem, + Separator as BreadcrumbSeparator, + Link as BreadcrumbLink, + List as BreadcrumbList, + Page as BreadcrumbPage, +}; diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte new file mode 100644 index 0000000..1938536 --- /dev/null +++ b/src/lib/components/ui/button/button.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts new file mode 100644 index 0000000..a927293 --- /dev/null +++ b/src/lib/components/ui/button/index.ts @@ -0,0 +1,49 @@ +import { type VariantProps, tv } from "tailwind-variants"; +import type { Button as ButtonPrimitive } from "bits-ui"; +import Root from "./button.svelte"; + +const buttonVariants = tv({ + base: "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +type Variant = VariantProps["variant"]; +type Size = VariantProps["size"]; + +type Props = ButtonPrimitive.Props & { + variant?: Variant; + size?: Size; +}; + +type Events = ButtonPrimitive.Events; + +export { + Root, + type Props, + type Events, + // + Root as Button, + type Props as ButtonProps, + type Events as ButtonEvents, + buttonVariants, +}; 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..2fb02fc --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-cell.svelte @@ -0,0 +1,21 @@ + + + + + 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..4e5434b --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-day.svelte @@ -0,0 +1,42 @@ + + + + + {date.day} + + 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..d93e7af --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-body.svelte @@ -0,0 +1,13 @@ + + + + + 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..00a532d --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-head.svelte @@ -0,0 +1,13 @@ + + + + + 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..8b21d4f --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-row.svelte @@ -0,0 +1,13 @@ + + + + + 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..8c2fe9d --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid.svelte @@ -0,0 +1,13 @@ + + + + + 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..d892520 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-head-cell.svelte @@ -0,0 +1,16 @@ + + + + + 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..1cd89da --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-header.svelte @@ -0,0 +1,16 @@ + + + + + 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..7c94798 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-heading.svelte @@ -0,0 +1,19 @@ + + + + + {headingValue} + + 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..05db866 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-months.svelte @@ -0,0 +1,16 @@ + + +
    + +
    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..af2071a --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-next-button.svelte @@ -0,0 +1,27 @@ + + + + + + + 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..d496ca6 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-prev-button.svelte @@ -0,0 +1,27 @@ + + + + + + + diff --git a/src/lib/components/ui/calendar/calendar.svelte b/src/lib/components/ui/calendar/calendar.svelte new file mode 100644 index 0000000..936af78 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar.svelte @@ -0,0 +1,59 @@ + + + + + + + + + + {#each months as month} + + + + {#each weekdays as weekday} + + {weekday.slice(0, 2)} + + {/each} + + + + {#each month.weeks as weekDates} + + {#each weekDates as date} + + + + {/each} + + {/each} + + + {/each} + + diff --git a/src/lib/components/ui/calendar/index.ts b/src/lib/components/ui/calendar/index.ts new file mode 100644 index 0000000..ab257ab --- /dev/null +++ b/src/lib/components/ui/calendar/index.ts @@ -0,0 +1,30 @@ +import Root from "./calendar.svelte"; +import Cell from "./calendar-cell.svelte"; +import Day from "./calendar-day.svelte"; +import Grid from "./calendar-grid.svelte"; +import Header from "./calendar-header.svelte"; +import Months from "./calendar-months.svelte"; +import GridRow from "./calendar-grid-row.svelte"; +import Heading from "./calendar-heading.svelte"; +import GridBody from "./calendar-grid-body.svelte"; +import GridHead from "./calendar-grid-head.svelte"; +import HeadCell from "./calendar-head-cell.svelte"; +import NextButton from "./calendar-next-button.svelte"; +import PrevButton from "./calendar-prev-button.svelte"; + +export { + Day, + Cell, + Grid, + Header, + Months, + GridRow, + Heading, + GridBody, + GridHead, + HeadCell, + NextButton, + PrevButton, + // + Root as Calendar, +}; 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..2fe0500 --- /dev/null +++ b/src/lib/components/ui/card/card-content.svelte @@ -0,0 +1,13 @@ + + +
    + +
    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..ade2b33 --- /dev/null +++ b/src/lib/components/ui/card/card-description.svelte @@ -0,0 +1,13 @@ + + +

    + +

    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..674538e --- /dev/null +++ b/src/lib/components/ui/card/card-footer.svelte @@ -0,0 +1,13 @@ + + +
    + +
    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..4541a33 --- /dev/null +++ b/src/lib/components/ui/card/card-header.svelte @@ -0,0 +1,13 @@ + + +
    + +
    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..fbc2224 --- /dev/null +++ b/src/lib/components/ui/card/card-title.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/ui/card/card.svelte b/src/lib/components/ui/card/card.svelte new file mode 100644 index 0000000..a243822 --- /dev/null +++ b/src/lib/components/ui/card/card.svelte @@ -0,0 +1,16 @@ + + +
    + +
    diff --git a/src/lib/components/ui/card/index.ts b/src/lib/components/ui/card/index.ts new file mode 100644 index 0000000..bcc031d --- /dev/null +++ b/src/lib/components/ui/card/index.ts @@ -0,0 +1,24 @@ +import Root from "./card.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"; + +export { + Root, + Content, + Description, + Footer, + Header, + Title, + // + Root as Card, + Content as CardContent, + Description as CardDescription, + Footer as CardFooter, + Header as CardHeader, + Title as CardTitle, +}; + +export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; 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..7f96b75 --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-content.svelte @@ -0,0 +1,35 @@ + + +
    +
    + +
    +
    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..3ca2c8e --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-item.svelte @@ -0,0 +1,25 @@ + + +
    + +
    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..606a977 --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-next.svelte @@ -0,0 +1,39 @@ + + + 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..af43eb1 --- /dev/null +++ b/src/lib/components/ui/carousel/carousel-previous.svelte @@ -0,0 +1,40 @@ + + + diff --git a/src/lib/components/ui/carousel/carousel.svelte b/src/lib/components/ui/carousel/carousel.svelte new file mode 100644 index 0000000..1d33938 --- /dev/null +++ b/src/lib/components/ui/carousel/carousel.svelte @@ -0,0 +1,98 @@ + + +
    + +
    diff --git a/src/lib/components/ui/carousel/context.ts b/src/lib/components/ui/carousel/context.ts new file mode 100644 index 0000000..c90b4cb --- /dev/null +++ b/src/lib/components/ui/carousel/context.ts @@ -0,0 +1,56 @@ +import type { EmblaCarouselSvelteType } from "embla-carousel-svelte"; +import type emblaCarouselSvelte from "embla-carousel-svelte"; +import { getContext, hasContext, setContext } from "svelte"; +import type { HTMLAttributes } from "svelte/elements"; +import type { Readable, Writable } from "svelte/store"; + +export type CarouselAPI = + NonNullable["on:emblaInit"]> extends ( + evt: CustomEvent + ) => void + ? CarouselAPI + : never; + +type EmblaCarouselConfig = NonNullable[1]>; + +export type CarouselOptions = EmblaCarouselConfig["options"]; +export type CarouselPlugins = EmblaCarouselConfig["plugins"]; + +//// + +export type CarouselProps = { + opts?: CarouselOptions; + plugins?: CarouselPlugins; + api?: CarouselAPI; + orientation?: "horizontal" | "vertical"; +} & HTMLAttributes; + +const EMBLA_CAROUSEL_CONTEXT = Symbol("EMBLA_CAROUSEL_CONTEXT"); + +type EmblaContext = { + api: Writable; + orientation: Writable<"horizontal" | "vertical">; + scrollNext: () => void; + scrollPrev: () => void; + canScrollNext: Readable; + canScrollPrev: Readable; + handleKeyDown: (e: KeyboardEvent) => void; + options: Writable; + plugins: Writable; + onInit: (e: CustomEvent) => void; + scrollTo: (index: number, jump?: boolean) => void; + scrollSnaps: Readable; + selectedIndex: Readable; +}; + +export function setEmblaContext(config: EmblaContext): EmblaContext { + setContext(EMBLA_CAROUSEL_CONTEXT, config); + return config; +} + +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); +} diff --git a/src/lib/components/ui/carousel/index.ts b/src/lib/components/ui/carousel/index.ts new file mode 100644 index 0000000..78102bf --- /dev/null +++ b/src/lib/components/ui/carousel/index.ts @@ -0,0 +1,5 @@ +export { default as Root } from "./carousel.svelte"; +export { default as Content } from "./carousel-content.svelte"; +export { default as Item } from "./carousel-item.svelte"; +export { default as Previous } from "./carousel-previous.svelte"; +export { default as Next } from "./carousel-next.svelte"; diff --git a/src/lib/components/ui/checkbox/checkbox.svelte b/src/lib/components/ui/checkbox/checkbox.svelte new file mode 100644 index 0000000..dd0b645 --- /dev/null +++ b/src/lib/components/ui/checkbox/checkbox.svelte @@ -0,0 +1,35 @@ + + + + + {#if isChecked} + + {:else if isIndeterminate} + + {/if} + + diff --git a/src/lib/components/ui/checkbox/index.ts b/src/lib/components/ui/checkbox/index.ts new file mode 100644 index 0000000..6d92d94 --- /dev/null +++ b/src/lib/components/ui/checkbox/index.ts @@ -0,0 +1,6 @@ +import Root from "./checkbox.svelte"; +export { + Root, + // + Root as Checkbox, +}; 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..2a8e5fa --- /dev/null +++ b/src/lib/components/ui/collapsible/collapsible-content.svelte @@ -0,0 +1,15 @@ + + + + + diff --git a/src/lib/components/ui/collapsible/index.ts b/src/lib/components/ui/collapsible/index.ts new file mode 100644 index 0000000..168834e --- /dev/null +++ b/src/lib/components/ui/collapsible/index.ts @@ -0,0 +1,15 @@ +import { Collapsible as CollapsiblePrimitive } from "bits-ui"; +import Content from "./collapsible-content.svelte"; + +const Root = CollapsiblePrimitive.Root; +const Trigger = CollapsiblePrimitive.Trigger; + +export { + Root, + Content, + Trigger, + // + Root as Collapsible, + Content as CollapsibleContent, + Trigger as CollapsibleTrigger, +}; 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..c6bb11a --- /dev/null +++ b/src/lib/components/ui/command/command-dialog.svelte @@ -0,0 +1,23 @@ + + + + + + + + + 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..e04a04c --- /dev/null +++ b/src/lib/components/ui/command/command-empty.svelte @@ -0,0 +1,12 @@ + + + + + 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..6120e24 --- /dev/null +++ b/src/lib/components/ui/command/command-group.svelte @@ -0,0 +1,18 @@ + + + + + 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..406d249 --- /dev/null +++ b/src/lib/components/ui/command/command-input.svelte @@ -0,0 +1,23 @@ + + +
    + + +
    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..77a8928 --- /dev/null +++ b/src/lib/components/ui/command/command-item.svelte @@ -0,0 +1,24 @@ + + + + + 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..252b72c --- /dev/null +++ b/src/lib/components/ui/command/command-list.svelte @@ -0,0 +1,15 @@ + + + + + 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..d67744a --- /dev/null +++ b/src/lib/components/ui/command/command-separator.svelte @@ -0,0 +1,10 @@ + + + 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..66e8b6d --- /dev/null +++ b/src/lib/components/ui/command/command-shortcut.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/command/command.svelte b/src/lib/components/ui/command/command.svelte new file mode 100644 index 0000000..b499fec --- /dev/null +++ b/src/lib/components/ui/command/command.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/src/lib/components/ui/command/index.ts b/src/lib/components/ui/command/index.ts new file mode 100644 index 0000000..d8a2e7c --- /dev/null +++ b/src/lib/components/ui/command/index.ts @@ -0,0 +1,37 @@ +import { Command as CommandPrimitive } from "cmdk-sv"; + +import Root from "./command.svelte"; +import Dialog from "./command-dialog.svelte"; +import Empty from "./command-empty.svelte"; +import Group from "./command-group.svelte"; +import Item from "./command-item.svelte"; +import Input from "./command-input.svelte"; +import List from "./command-list.svelte"; +import Separator from "./command-separator.svelte"; +import Shortcut from "./command-shortcut.svelte"; + +const Loading = CommandPrimitive.Loading; + +export { + Root, + Dialog, + Empty, + Group, + Item, + Input, + List, + Separator, + Shortcut, + Loading, + // + Root as Command, + Dialog as CommandDialog, + Empty as CommandEmpty, + Group as CommandGroup, + Item as CommandItem, + Input as CommandInput, + List as CommandList, + Separator as CommandSeparator, + Shortcut as CommandShortcut, + Loading as CommandLoading, +}; 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..bd5b782 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + 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..475d1e3 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-content.svelte @@ -0,0 +1,24 @@ + + + + + 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..b1c1210 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-item.svelte @@ -0,0 +1,31 @@ + + + + + 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..02ad5a9 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-label.svelte @@ -0,0 +1,19 @@ + + + + + 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..53fa692 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-radio-group.svelte @@ -0,0 +1,11 @@ + + + + + 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..09a9467 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + 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..f6a8a9e --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-separator.svelte @@ -0,0 +1,14 @@ + + + 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..9d5e145 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-shortcut.svelte @@ -0,0 +1,16 @@ + + + + + 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..d3df093 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub-content.svelte @@ -0,0 +1,29 @@ + + + + + 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..45c2a58 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte @@ -0,0 +1,32 @@ + + + + + + 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..7d4af84 --- /dev/null +++ b/src/lib/components/ui/context-menu/index.ts @@ -0,0 +1,49 @@ +import { ContextMenu as ContextMenuPrimitive } from "bits-ui"; + +import Item from "./context-menu-item.svelte"; +import Label from "./context-menu-label.svelte"; +import Content from "./context-menu-content.svelte"; +import Shortcut from "./context-menu-shortcut.svelte"; +import RadioItem from "./context-menu-radio-item.svelte"; +import Separator from "./context-menu-separator.svelte"; +import RadioGroup from "./context-menu-radio-group.svelte"; +import SubContent from "./context-menu-sub-content.svelte"; +import SubTrigger from "./context-menu-sub-trigger.svelte"; +import CheckboxItem from "./context-menu-checkbox-item.svelte"; + +const Sub = ContextMenuPrimitive.Sub; +const Root = ContextMenuPrimitive.Root; +const Trigger = ContextMenuPrimitive.Trigger; +const Group = ContextMenuPrimitive.Group; + +export { + Sub, + Root, + Item, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as ContextMenu, + Sub as ContextMenuSub, + Item as ContextMenuItem, + Label as ContextMenuLabel, + Group as ContextMenuGroup, + Content as ContextMenuContent, + Trigger as ContextMenuTrigger, + Shortcut as ContextMenuShortcut, + RadioItem as ContextMenuRadioItem, + Separator as ContextMenuSeparator, + RadioGroup as ContextMenuRadioGroup, + SubContent as ContextMenuSubContent, + SubTrigger as ContextMenuSubTrigger, + CheckboxItem as ContextMenuCheckboxItem, +}; 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..8de2a2e --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,36 @@ + + + + + + + + + Close + + + 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..d3efa27 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,16 @@ + + + + + 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..0b21f15 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,16 @@ + + +
    + +
    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..a1dbb88 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,13 @@ + + +
    + +
    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..9712be7 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,21 @@ + + + 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..eb5d0a5 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,8 @@ + + + + + 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..be26bf4 --- /dev/null +++ b/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/dialog/index.ts b/src/lib/components/ui/dialog/index.ts new file mode 100644 index 0000000..b17ba5e --- /dev/null +++ b/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,37 @@ +import { Dialog as DialogPrimitive } from "bits-ui"; + +import Title from "./dialog-title.svelte"; +import Portal from "./dialog-portal.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; + +const Root = DialogPrimitive.Root; +const Trigger = DialogPrimitive.Trigger; +const Close = DialogPrimitive.Close; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose, +}; 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..86f9f0a --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-content.svelte @@ -0,0 +1,24 @@ + + + + + +
    + +
    +
    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..c1d6546 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-description.svelte @@ -0,0 +1,18 @@ + + + + + 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..fa6d255 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-footer.svelte @@ -0,0 +1,16 @@ + + +
    + +
    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..c3a8451 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-header.svelte @@ -0,0 +1,19 @@ + + +
    + +
    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..79b68e3 --- /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..20aa739 --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-overlay.svelte @@ -0,0 +1,18 @@ + + + + + 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..33c22af --- /dev/null +++ b/src/lib/components/ui/drawer/drawer-title.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/src/lib/components/ui/drawer/drawer.svelte b/src/lib/components/ui/drawer/drawer.svelte new file mode 100644 index 0000000..40eae5e --- /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..76932e3 --- /dev/null +++ b/src/lib/components/ui/drawer/index.ts @@ -0,0 +1,41 @@ +import { Drawer as DrawerPrimitive } from "vaul-svelte"; + +import Root from "./drawer.svelte"; +import Content from "./drawer-content.svelte"; +import Description from "./drawer-description.svelte"; +import Overlay from "./drawer-overlay.svelte"; +import Footer from "./drawer-footer.svelte"; +import Header from "./drawer-header.svelte"; +import Title from "./drawer-title.svelte"; +import NestedRoot from "./drawer-nested.svelte"; + +const Trigger = DrawerPrimitive.Trigger; +const Portal = DrawerPrimitive.Portal; +const Close = DrawerPrimitive.Close; + +export { + Root, + NestedRoot, + Content, + Description, + Overlay, + Footer, + Header, + Title, + Trigger, + Portal, + Close, + + // + Root as Drawer, + NestedRoot as DrawerNestedRoot, + Content as DrawerContent, + Description as DrawerDescription, + Overlay as DrawerOverlay, + Footer as DrawerFooter, + Header as DrawerHeader, + Title as DrawerTitle, + Trigger as DrawerTrigger, + Portal as DrawerPortal, + Close as DrawerClose, +}; 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..caf543c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + 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..0994c3b --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,27 @@ + + + + + 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..ba1cdaa --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,31 @@ + + + + + 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..512692b --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,19 @@ + + + + + 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..1c74ae1 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,11 @@ + + + + + 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..05855e0 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + 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..948ba9c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,14 @@ + + + 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..55945e8 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,13 @@ + + + + + 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..246f010 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,30 @@ + + + + + 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..082e2ac --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,32 @@ + + + + + + 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..c1749e9 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,48 @@ +import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui"; +import Item from "./dropdown-menu-item.svelte"; +import Label from "./dropdown-menu-label.svelte"; +import Content from "./dropdown-menu-content.svelte"; +import Shortcut from "./dropdown-menu-shortcut.svelte"; +import RadioItem from "./dropdown-menu-radio-item.svelte"; +import Separator from "./dropdown-menu-separator.svelte"; +import RadioGroup from "./dropdown-menu-radio-group.svelte"; +import SubContent from "./dropdown-menu-sub-content.svelte"; +import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; +import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; + +const Sub = DropdownMenuPrimitive.Sub; +const Root = DropdownMenuPrimitive.Root; +const Trigger = DropdownMenuPrimitive.Trigger; +const Group = DropdownMenuPrimitive.Group; + +export { + Sub, + Root, + Item, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as DropdownMenu, + Sub as DropdownMenuSub, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + Group as DropdownMenuGroup, + Content as DropdownMenuContent, + Trigger as DropdownMenuTrigger, + Shortcut as DropdownMenuShortcut, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + RadioGroup as DropdownMenuRadioGroup, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + CheckboxItem as DropdownMenuCheckboxItem, +}; 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..087c839 --- /dev/null +++ b/src/lib/components/ui/form/form-button.svelte @@ -0,0 +1,10 @@ + + + + + diff --git a/src/lib/components/ui/form/form-description.svelte b/src/lib/components/ui/form/form-description.svelte new file mode 100644 index 0000000..2829644 --- /dev/null +++ b/src/lib/components/ui/form/form-description.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/src/lib/components/ui/form/form-element-field.svelte b/src/lib/components/ui/form/form-element-field.svelte new file mode 100644 index 0000000..bf5dd43 --- /dev/null +++ b/src/lib/components/ui/form/form-element-field.svelte @@ -0,0 +1,25 @@ + + + + + +
    + +
    +
    diff --git a/src/lib/components/ui/form/form-field-errors.svelte b/src/lib/components/ui/form/form-field-errors.svelte new file mode 100644 index 0000000..540d979 --- /dev/null +++ b/src/lib/components/ui/form/form-field-errors.svelte @@ -0,0 +1,26 @@ + + + + + {#each errors as error} +
    {error}
    + {/each} +
    +
    diff --git a/src/lib/components/ui/form/form-field.svelte b/src/lib/components/ui/form/form-field.svelte new file mode 100644 index 0000000..c58b1f7 --- /dev/null +++ b/src/lib/components/ui/form/form-field.svelte @@ -0,0 +1,25 @@ + + + + + +
    + +
    +
    diff --git a/src/lib/components/ui/form/form-fieldset.svelte b/src/lib/components/ui/form/form-fieldset.svelte new file mode 100644 index 0000000..71993b4 --- /dev/null +++ b/src/lib/components/ui/form/form-fieldset.svelte @@ -0,0 +1,30 @@ + + + + + + + diff --git a/src/lib/components/ui/form/form-label.svelte b/src/lib/components/ui/form/form-label.svelte new file mode 100644 index 0000000..e72a8db --- /dev/null +++ b/src/lib/components/ui/form/form-label.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/form/form-legend.svelte b/src/lib/components/ui/form/form-legend.svelte new file mode 100644 index 0000000..8a843cf --- /dev/null +++ b/src/lib/components/ui/form/form-legend.svelte @@ -0,0 +1,17 @@ + + + + + diff --git a/src/lib/components/ui/form/index.ts b/src/lib/components/ui/form/index.ts new file mode 100644 index 0000000..0713927 --- /dev/null +++ b/src/lib/components/ui/form/index.ts @@ -0,0 +1,33 @@ +import * as FormPrimitive from "formsnap"; +import Description from "./form-description.svelte"; +import Label from "./form-label.svelte"; +import FieldErrors from "./form-field-errors.svelte"; +import Field from "./form-field.svelte"; +import Fieldset from "./form-fieldset.svelte"; +import Legend from "./form-legend.svelte"; +import ElementField from "./form-element-field.svelte"; +import Button from "./form-button.svelte"; + +const Control = FormPrimitive.Control; + +export { + Field, + Control, + Label, + Button, + FieldErrors, + Description, + Fieldset, + Legend, + ElementField, + // + Field as FormField, + Control as FormControl, + Description as FormDescription, + Label as FormLabel, + FieldErrors as FormFieldErrors, + Fieldset as FormFieldset, + Legend as FormLegend, + ElementField as FormElementField, + Button as FormButton, +}; diff --git a/src/lib/components/ui/hover-card/hover-card-content.svelte b/src/lib/components/ui/hover-card/hover-card-content.svelte new file mode 100644 index 0000000..003a423 --- /dev/null +++ b/src/lib/components/ui/hover-card/hover-card-content.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/src/lib/components/ui/hover-card/index.ts b/src/lib/components/ui/hover-card/index.ts new file mode 100644 index 0000000..2d0c5c5 --- /dev/null +++ b/src/lib/components/ui/hover-card/index.ts @@ -0,0 +1,14 @@ +import { LinkPreview as HoverCardPrimitive } from "bits-ui"; + +import Content from "./hover-card-content.svelte"; +const Root = HoverCardPrimitive.Root; +const Trigger = HoverCardPrimitive.Trigger; + +export { + Root, + Content, + Trigger, + Root as HoverCard, + Content as HoverCardContent, + Trigger as HoverCardTrigger, +}; diff --git a/src/lib/components/ui/input/index.ts b/src/lib/components/ui/input/index.ts new file mode 100644 index 0000000..75e3bc2 --- /dev/null +++ b/src/lib/components/ui/input/index.ts @@ -0,0 +1,29 @@ +import Root from "./input.svelte"; + +export type FormInputEvent = T & { + currentTarget: EventTarget & HTMLInputElement; +}; +export type InputEvents = { + blur: FormInputEvent; + change: FormInputEvent; + click: FormInputEvent; + focus: FormInputEvent; + focusin: FormInputEvent; + focusout: FormInputEvent; + keydown: FormInputEvent; + keypress: FormInputEvent; + keyup: FormInputEvent; + mouseover: FormInputEvent; + mouseenter: FormInputEvent; + mouseleave: FormInputEvent; + mousemove: FormInputEvent; + paste: FormInputEvent; + input: FormInputEvent; + wheel: FormInputEvent; +}; + +export { + Root, + // + Root as Input, +}; diff --git a/src/lib/components/ui/input/input.svelte b/src/lib/components/ui/input/input.svelte new file mode 100644 index 0000000..aec2eb6 --- /dev/null +++ b/src/lib/components/ui/input/input.svelte @@ -0,0 +1,42 @@ + + + diff --git a/src/lib/components/ui/label/index.ts b/src/lib/components/ui/label/index.ts new file mode 100644 index 0000000..8bfca0b --- /dev/null +++ b/src/lib/components/ui/label/index.ts @@ -0,0 +1,7 @@ +import Root from "./label.svelte"; + +export { + Root, + // + Root as Label, +}; diff --git a/src/lib/components/ui/label/label.svelte b/src/lib/components/ui/label/label.svelte new file mode 100644 index 0000000..2da3aa1 --- /dev/null +++ b/src/lib/components/ui/label/label.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/ui/menubar/index.ts b/src/lib/components/ui/menubar/index.ts new file mode 100644 index 0000000..62e01eb --- /dev/null +++ b/src/lib/components/ui/menubar/index.ts @@ -0,0 +1,52 @@ +import { Menubar as MenubarPrimitive } from "bits-ui"; + +import Root from "./menubar.svelte"; +import CheckboxItem from "./menubar-checkbox-item.svelte"; +import Content from "./menubar-content.svelte"; +import Item from "./menubar-item.svelte"; +import Label from "./menubar-label.svelte"; +import RadioItem from "./menubar-radio-item.svelte"; +import Separator from "./menubar-separator.svelte"; +import Shortcut from "./menubar-shortcut.svelte"; +import SubContent from "./menubar-sub-content.svelte"; +import SubTrigger from "./menubar-sub-trigger.svelte"; +import Trigger from "./menubar-trigger.svelte"; + +const Menu = MenubarPrimitive.Menu; +const Group = MenubarPrimitive.Group; +const Sub = MenubarPrimitive.Sub; +const RadioGroup = MenubarPrimitive.RadioGroup; + +export { + Root, + CheckboxItem, + Content, + Item, + Label, + RadioItem, + Separator, + Shortcut, + SubContent, + SubTrigger, + Trigger, + Menu, + Group, + Sub, + RadioGroup, + // + Root as Menubar, + CheckboxItem as MenubarCheckboxItem, + Content as MenubarContent, + Item as MenubarItem, + Label as MenubarLabel, + RadioItem as MenubarRadioItem, + Separator as MenubarSeparator, + Shortcut as MenubarShortcut, + SubContent as MenubarSubContent, + SubTrigger as MenubarSubTrigger, + Trigger as MenubarTrigger, + Menu as MenubarMenu, + Group as MenubarGroup, + Sub as MenubarSub, + RadioGroup as MenubarRadioGroup, +}; diff --git a/src/lib/components/ui/menubar/menubar-checkbox-item.svelte b/src/lib/components/ui/menubar/menubar-checkbox-item.svelte new file mode 100644 index 0000000..67be18b --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-checkbox-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/src/lib/components/ui/menubar/menubar-content.svelte b/src/lib/components/ui/menubar/menubar-content.svelte new file mode 100644 index 0000000..c612f26 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-content.svelte @@ -0,0 +1,33 @@ + + + + + diff --git a/src/lib/components/ui/menubar/menubar-item.svelte b/src/lib/components/ui/menubar/menubar-item.svelte new file mode 100644 index 0000000..814d2ef --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-item.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/src/lib/components/ui/menubar/menubar-label.svelte b/src/lib/components/ui/menubar/menubar-label.svelte new file mode 100644 index 0000000..37f4781 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-label.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/lib/components/ui/menubar/menubar-radio-item.svelte b/src/lib/components/ui/menubar/menubar-radio-item.svelte new file mode 100644 index 0000000..abb19a1 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-radio-item.svelte @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/src/lib/components/ui/menubar/menubar-separator.svelte b/src/lib/components/ui/menubar/menubar-separator.svelte new file mode 100644 index 0000000..7af2be5 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-separator.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/menubar/menubar-shortcut.svelte b/src/lib/components/ui/menubar/menubar-shortcut.svelte new file mode 100644 index 0000000..9d5e145 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-shortcut.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/menubar/menubar-sub-content.svelte b/src/lib/components/ui/menubar/menubar-sub-content.svelte new file mode 100644 index 0000000..f7e4bc5 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-sub-content.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/src/lib/components/ui/menubar/menubar-sub-trigger.svelte b/src/lib/components/ui/menubar/menubar-sub-trigger.svelte new file mode 100644 index 0000000..84746b4 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-sub-trigger.svelte @@ -0,0 +1,32 @@ + + + + + + diff --git a/src/lib/components/ui/menubar/menubar-trigger.svelte b/src/lib/components/ui/menubar/menubar-trigger.svelte new file mode 100644 index 0000000..4dd28e6 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar-trigger.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/src/lib/components/ui/menubar/menubar.svelte b/src/lib/components/ui/menubar/menubar.svelte new file mode 100644 index 0000000..9fb8616 --- /dev/null +++ b/src/lib/components/ui/menubar/menubar.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/pagination/index.ts b/src/lib/components/ui/pagination/index.ts new file mode 100644 index 0000000..d83c7a9 --- /dev/null +++ b/src/lib/components/ui/pagination/index.ts @@ -0,0 +1,25 @@ +import Root from "./pagination.svelte"; +import Content from "./pagination-content.svelte"; +import Item from "./pagination-item.svelte"; +import Link from "./pagination-link.svelte"; +import PrevButton from "./pagination-prev-button.svelte"; +import NextButton from "./pagination-next-button.svelte"; +import Ellipsis from "./pagination-ellipsis.svelte"; + +export { + Root, + Content, + Item, + Link, + PrevButton, + NextButton, + Ellipsis, + // + Root as Pagination, + Content as PaginationContent, + Item as PaginationItem, + Link as PaginationLink, + PrevButton as PaginationPrevButton, + NextButton as PaginationNextButton, + Ellipsis as PaginationEllipsis, +}; diff --git a/src/lib/components/ui/pagination/pagination-content.svelte b/src/lib/components/ui/pagination/pagination-content.svelte new file mode 100644 index 0000000..2cf3100 --- /dev/null +++ b/src/lib/components/ui/pagination/pagination-content.svelte @@ -0,0 +1,13 @@ + + +
      + +
    diff --git a/src/lib/components/ui/pagination/pagination-ellipsis.svelte b/src/lib/components/ui/pagination/pagination-ellipsis.svelte new file mode 100644 index 0000000..51eb86a --- /dev/null +++ b/src/lib/components/ui/pagination/pagination-ellipsis.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/pagination/pagination-item.svelte b/src/lib/components/ui/pagination/pagination-item.svelte new file mode 100644 index 0000000..ab603c6 --- /dev/null +++ b/src/lib/components/ui/pagination/pagination-item.svelte @@ -0,0 +1,13 @@ + + +
  • + +
  • diff --git a/src/lib/components/ui/pagination/pagination-link.svelte b/src/lib/components/ui/pagination/pagination-link.svelte new file mode 100644 index 0000000..6482403 --- /dev/null +++ b/src/lib/components/ui/pagination/pagination-link.svelte @@ -0,0 +1,34 @@ + + + + {page.value} + diff --git a/src/lib/components/ui/pagination/pagination-next-button.svelte b/src/lib/components/ui/pagination/pagination-next-button.svelte new file mode 100644 index 0000000..f087956 --- /dev/null +++ b/src/lib/components/ui/pagination/pagination-next-button.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/src/lib/components/ui/pagination/pagination-prev-button.svelte b/src/lib/components/ui/pagination/pagination-prev-button.svelte new file mode 100644 index 0000000..1101b21 --- /dev/null +++ b/src/lib/components/ui/pagination/pagination-prev-button.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/src/lib/components/ui/pagination/pagination.svelte b/src/lib/components/ui/pagination/pagination.svelte new file mode 100644 index 0000000..46033d5 --- /dev/null +++ b/src/lib/components/ui/pagination/pagination.svelte @@ -0,0 +1,33 @@ + + + + + diff --git a/src/lib/components/ui/popover/index.ts b/src/lib/components/ui/popover/index.ts new file mode 100644 index 0000000..63aecf9 --- /dev/null +++ b/src/lib/components/ui/popover/index.ts @@ -0,0 +1,17 @@ +import { Popover as PopoverPrimitive } from "bits-ui"; +import Content from "./popover-content.svelte"; +const Root = PopoverPrimitive.Root; +const Trigger = PopoverPrimitive.Trigger; +const Close = PopoverPrimitive.Close; + +export { + Root, + Content, + Trigger, + Close, + // + Root as Popover, + Content as PopoverContent, + Trigger as PopoverTrigger, + Close as PopoverClose, +}; diff --git a/src/lib/components/ui/popover/popover-content.svelte b/src/lib/components/ui/popover/popover-content.svelte new file mode 100644 index 0000000..13f362e --- /dev/null +++ b/src/lib/components/ui/popover/popover-content.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/src/lib/components/ui/progress/index.ts b/src/lib/components/ui/progress/index.ts new file mode 100644 index 0000000..25eee61 --- /dev/null +++ b/src/lib/components/ui/progress/index.ts @@ -0,0 +1,7 @@ +import Root from "./progress.svelte"; + +export { + Root, + // + Root as Progress, +}; diff --git a/src/lib/components/ui/progress/progress.svelte b/src/lib/components/ui/progress/progress.svelte new file mode 100644 index 0000000..51c1874 --- /dev/null +++ b/src/lib/components/ui/progress/progress.svelte @@ -0,0 +1,21 @@ + + + +
    +
    diff --git a/src/lib/components/ui/radio-group/index.ts b/src/lib/components/ui/radio-group/index.ts new file mode 100644 index 0000000..feefa79 --- /dev/null +++ b/src/lib/components/ui/radio-group/index.ts @@ -0,0 +1,15 @@ +import { RadioGroup as RadioGroupPrimitive } from "bits-ui"; + +import Root from "./radio-group.svelte"; +import Item from "./radio-group-item.svelte"; +const Input = RadioGroupPrimitive.Input; + +export { + Root, + Input, + Item, + // + Root as RadioGroup, + Input as RadioGroupInput, + Item as RadioGroupItem, +}; diff --git a/src/lib/components/ui/radio-group/radio-group-item.svelte b/src/lib/components/ui/radio-group/radio-group-item.svelte new file mode 100644 index 0000000..93e4464 --- /dev/null +++ b/src/lib/components/ui/radio-group/radio-group-item.svelte @@ -0,0 +1,28 @@ + + + +
    + + + +
    +
    diff --git a/src/lib/components/ui/radio-group/radio-group.svelte b/src/lib/components/ui/radio-group/radio-group.svelte new file mode 100644 index 0000000..62b1053 --- /dev/null +++ b/src/lib/components/ui/radio-group/radio-group.svelte @@ -0,0 +1,14 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/index.ts b/src/lib/components/ui/range-calendar/index.ts new file mode 100644 index 0000000..43adb92 --- /dev/null +++ b/src/lib/components/ui/range-calendar/index.ts @@ -0,0 +1,30 @@ +import Root from "./range-calendar.svelte"; +import Cell from "./range-calendar-cell.svelte"; +import Day from "./range-calendar-day.svelte"; +import Grid from "./range-calendar-grid.svelte"; +import Header from "./range-calendar-header.svelte"; +import Months from "./range-calendar-months.svelte"; +import GridRow from "./range-calendar-grid-row.svelte"; +import Heading from "./range-calendar-heading.svelte"; +import GridBody from "./range-calendar-grid-body.svelte"; +import GridHead from "./range-calendar-grid-head.svelte"; +import HeadCell from "./range-calendar-head-cell.svelte"; +import NextButton from "./range-calendar-next-button.svelte"; +import PrevButton from "./range-calendar-prev-button.svelte"; + +export { + Day, + Cell, + Grid, + Header, + Months, + GridRow, + Heading, + GridBody, + GridHead, + HeadCell, + NextButton, + PrevButton, + // + Root as RangeCalendar, +}; diff --git a/src/lib/components/ui/range-calendar/range-calendar-cell.svelte b/src/lib/components/ui/range-calendar/range-calendar-cell.svelte new file mode 100644 index 0000000..53f2555 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-cell.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-day.svelte b/src/lib/components/ui/range-calendar/range-calendar-day.svelte new file mode 100644 index 0000000..4168b45 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-day.svelte @@ -0,0 +1,43 @@ + + + + + {date.day} + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte b/src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte new file mode 100644 index 0000000..70c3f2d --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte b/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte new file mode 100644 index 0000000..0045d02 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte b/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte new file mode 100644 index 0000000..29e664e --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-grid.svelte b/src/lib/components/ui/range-calendar/range-calendar-grid.svelte new file mode 100644 index 0000000..6d7c58c --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-grid.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte b/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte new file mode 100644 index 0000000..3a20372 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-header.svelte b/src/lib/components/ui/range-calendar/range-calendar-header.svelte new file mode 100644 index 0000000..81a73d4 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-header.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-heading.svelte b/src/lib/components/ui/range-calendar/range-calendar-heading.svelte new file mode 100644 index 0000000..56f6af1 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-heading.svelte @@ -0,0 +1,19 @@ + + + + + {headingValue} + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-months.svelte b/src/lib/components/ui/range-calendar/range-calendar-months.svelte new file mode 100644 index 0000000..05db866 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-months.svelte @@ -0,0 +1,16 @@ + + +
    + +
    diff --git a/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte b/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte new file mode 100644 index 0000000..5c34106 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte @@ -0,0 +1,27 @@ + + + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte b/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte new file mode 100644 index 0000000..4aba2c0 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte @@ -0,0 +1,27 @@ + + + + + + + diff --git a/src/lib/components/ui/range-calendar/range-calendar.svelte b/src/lib/components/ui/range-calendar/range-calendar.svelte new file mode 100644 index 0000000..c446db7 --- /dev/null +++ b/src/lib/components/ui/range-calendar/range-calendar.svelte @@ -0,0 +1,60 @@ + + + + + + + + + + {#each months as month} + + + + {#each weekdays as weekday} + + {weekday.slice(0, 2)} + + {/each} + + + + {#each month.weeks as weekDates} + + {#each weekDates as date} + + + + {/each} + + {/each} + + + {/each} + + diff --git a/src/lib/components/ui/resizable/index.ts b/src/lib/components/ui/resizable/index.ts new file mode 100644 index 0000000..2e37f11 --- /dev/null +++ b/src/lib/components/ui/resizable/index.ts @@ -0,0 +1,13 @@ +import { Pane } from "paneforge"; +import Handle from "./resizable-handle.svelte"; +import PaneGroup from "./resizable-pane-group.svelte"; + +export { + PaneGroup, + Pane, + Handle, + // + PaneGroup as ResizablePaneGroup, + Pane as ResizablePane, + Handle as ResizableHandle, +}; diff --git a/src/lib/components/ui/resizable/resizable-handle.svelte b/src/lib/components/ui/resizable/resizable-handle.svelte new file mode 100644 index 0000000..fe70231 --- /dev/null +++ b/src/lib/components/ui/resizable/resizable-handle.svelte @@ -0,0 +1,28 @@ + + +div]:rotate-90", + className + )} +> + {#if withHandle} +
    + +
    + {/if} +
    diff --git a/src/lib/components/ui/resizable/resizable-pane-group.svelte b/src/lib/components/ui/resizable/resizable-pane-group.svelte new file mode 100644 index 0000000..0961469 --- /dev/null +++ b/src/lib/components/ui/resizable/resizable-pane-group.svelte @@ -0,0 +1,22 @@ + + + + + diff --git a/src/lib/components/ui/scroll-area/index.ts b/src/lib/components/ui/scroll-area/index.ts new file mode 100644 index 0000000..e86a25b --- /dev/null +++ b/src/lib/components/ui/scroll-area/index.ts @@ -0,0 +1,10 @@ +import Scrollbar from "./scroll-area-scrollbar.svelte"; +import Root from "./scroll-area.svelte"; + +export { + Root, + Scrollbar, + //, + Root as ScrollArea, + Scrollbar as ScrollAreaScrollbar, +}; diff --git a/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte b/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte new file mode 100644 index 0000000..4f86ea6 --- /dev/null +++ b/src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte @@ -0,0 +1,27 @@ + + + + + + diff --git a/src/lib/components/ui/scroll-area/scroll-area.svelte b/src/lib/components/ui/scroll-area/scroll-area.svelte new file mode 100644 index 0000000..c0403d9 --- /dev/null +++ b/src/lib/components/ui/scroll-area/scroll-area.svelte @@ -0,0 +1,32 @@ + + + + + + + + + {#if orientation === "vertical" || orientation === "both"} + + {/if} + {#if orientation === "horizontal" || orientation === "both"} + + {/if} + + diff --git a/src/lib/components/ui/select/index.ts b/src/lib/components/ui/select/index.ts new file mode 100644 index 0000000..327541c --- /dev/null +++ b/src/lib/components/ui/select/index.ts @@ -0,0 +1,34 @@ +import { Select as SelectPrimitive } from "bits-ui"; + +import Label from "./select-label.svelte"; +import Item from "./select-item.svelte"; +import Content from "./select-content.svelte"; +import Trigger from "./select-trigger.svelte"; +import Separator from "./select-separator.svelte"; + +const Root = SelectPrimitive.Root; +const Group = SelectPrimitive.Group; +const Input = SelectPrimitive.Input; +const Value = SelectPrimitive.Value; + +export { + Root, + Group, + Input, + Label, + Item, + Value, + Content, + Trigger, + Separator, + // + Root as Select, + Group as SelectGroup, + Input as SelectInput, + Label as SelectLabel, + Item as SelectItem, + Value as SelectValue, + Content as SelectContent, + Trigger as SelectTrigger, + Separator as SelectSeparator, +}; diff --git a/src/lib/components/ui/select/select-content.svelte b/src/lib/components/ui/select/select-content.svelte new file mode 100644 index 0000000..6ff560d --- /dev/null +++ b/src/lib/components/ui/select/select-content.svelte @@ -0,0 +1,39 @@ + + + +
    + +
    +
    diff --git a/src/lib/components/ui/select/select-item.svelte b/src/lib/components/ui/select/select-item.svelte new file mode 100644 index 0000000..48a594f --- /dev/null +++ b/src/lib/components/ui/select/select-item.svelte @@ -0,0 +1,40 @@ + + + + + + + + + + {label || value} + + diff --git a/src/lib/components/ui/select/select-label.svelte b/src/lib/components/ui/select/select-label.svelte new file mode 100644 index 0000000..6ae46f1 --- /dev/null +++ b/src/lib/components/ui/select/select-label.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/select/select-separator.svelte b/src/lib/components/ui/select/select-separator.svelte new file mode 100644 index 0000000..7ef3360 --- /dev/null +++ b/src/lib/components/ui/select/select-separator.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/lib/components/ui/select/select-trigger.svelte b/src/lib/components/ui/select/select-trigger.svelte new file mode 100644 index 0000000..eb5f72e --- /dev/null +++ b/src/lib/components/ui/select/select-trigger.svelte @@ -0,0 +1,27 @@ + + +span]:line-clamp-1 data-[placeholder]:[&>span]:text-muted-foreground", + className + )} + {...$$restProps} + let:builder + on:click + on:keydown +> + +
    + +
    +
    diff --git a/src/lib/components/ui/separator/index.ts b/src/lib/components/ui/separator/index.ts new file mode 100644 index 0000000..82442d2 --- /dev/null +++ b/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from "./separator.svelte"; + +export { + Root, + // + Root as Separator, +}; diff --git a/src/lib/components/ui/separator/separator.svelte b/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 0000000..2fe3164 --- /dev/null +++ b/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,22 @@ + + + diff --git a/src/lib/components/ui/sheet/index.ts b/src/lib/components/ui/sheet/index.ts new file mode 100644 index 0000000..1a69032 --- /dev/null +++ b/src/lib/components/ui/sheet/index.ts @@ -0,0 +1,106 @@ +import { Dialog as SheetPrimitive } from "bits-ui"; +import { type VariantProps, tv } from "tailwind-variants"; + +import Portal from "./sheet-portal.svelte"; +import Overlay from "./sheet-overlay.svelte"; +import Content from "./sheet-content.svelte"; +import Header from "./sheet-header.svelte"; +import Footer from "./sheet-footer.svelte"; +import Title from "./sheet-title.svelte"; +import Description from "./sheet-description.svelte"; + +const Root = SheetPrimitive.Root; +const Close = SheetPrimitive.Close; +const Trigger = SheetPrimitive.Trigger; + +export { + Root, + Close, + Trigger, + Portal, + Overlay, + Content, + Header, + Footer, + Title, + Description, + // + Root as Sheet, + Close as SheetClose, + Trigger as SheetTrigger, + Portal as SheetPortal, + Overlay as SheetOverlay, + Content as SheetContent, + Header as SheetHeader, + Footer as SheetFooter, + Title as SheetTitle, + Description as SheetDescription, +}; + +export const sheetVariants = tv({ + base: "fixed z-50 gap-4 bg-background p-6 shadow-lg", + variants: { + side: { + top: "inset-x-0 top-0 border-b", + bottom: "inset-x-0 bottom-0 border-t", + left: "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm", + right: "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm", + }, + }, + defaultVariants: { + side: "right", + }, +}); + +export const sheetTransitions = { + top: { + in: { + y: "-100%", + duration: 500, + opacity: 1, + }, + out: { + y: "-100%", + duration: 300, + opacity: 1, + }, + }, + bottom: { + in: { + y: "100%", + duration: 500, + opacity: 1, + }, + out: { + y: "100%", + duration: 300, + opacity: 1, + }, + }, + left: { + in: { + x: "-100%", + duration: 500, + opacity: 1, + }, + out: { + x: "-100%", + duration: 300, + opacity: 1, + }, + }, + right: { + in: { + x: "100%", + duration: 500, + opacity: 1, + }, + out: { + x: "100%", + duration: 300, + opacity: 1, + }, + }, +}; + +export type Side = VariantProps["side"]; diff --git a/src/lib/components/ui/sheet/sheet-content.svelte b/src/lib/components/ui/sheet/sheet-content.svelte new file mode 100644 index 0000000..c83eb11 --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-content.svelte @@ -0,0 +1,47 @@ + + + + + + + + + Close + + + diff --git a/src/lib/components/ui/sheet/sheet-description.svelte b/src/lib/components/ui/sheet/sheet-description.svelte new file mode 100644 index 0000000..b1892e4 --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-description.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/sheet/sheet-footer.svelte b/src/lib/components/ui/sheet/sheet-footer.svelte new file mode 100644 index 0000000..0b21f15 --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-footer.svelte @@ -0,0 +1,16 @@ + + +
    + +
    diff --git a/src/lib/components/ui/sheet/sheet-header.svelte b/src/lib/components/ui/sheet/sheet-header.svelte new file mode 100644 index 0000000..482977e --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-header.svelte @@ -0,0 +1,13 @@ + + +
    + +
    diff --git a/src/lib/components/ui/sheet/sheet-overlay.svelte b/src/lib/components/ui/sheet/sheet-overlay.svelte new file mode 100644 index 0000000..7d030d0 --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-overlay.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/lib/components/ui/sheet/sheet-portal.svelte b/src/lib/components/ui/sheet/sheet-portal.svelte new file mode 100644 index 0000000..99e7966 --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-portal.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/sheet/sheet-title.svelte b/src/lib/components/ui/sheet/sheet-title.svelte new file mode 100644 index 0000000..6ccacf6 --- /dev/null +++ b/src/lib/components/ui/sheet/sheet-title.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/src/lib/components/ui/skeleton/index.ts b/src/lib/components/ui/skeleton/index.ts new file mode 100644 index 0000000..186db21 --- /dev/null +++ b/src/lib/components/ui/skeleton/index.ts @@ -0,0 +1,7 @@ +import Root from "./skeleton.svelte"; + +export { + Root, + // + Root as Skeleton, +}; diff --git a/src/lib/components/ui/skeleton/skeleton.svelte b/src/lib/components/ui/skeleton/skeleton.svelte new file mode 100644 index 0000000..bff634f --- /dev/null +++ b/src/lib/components/ui/skeleton/skeleton.svelte @@ -0,0 +1,11 @@ + + +
    diff --git a/src/lib/components/ui/slider/index.ts b/src/lib/components/ui/slider/index.ts new file mode 100644 index 0000000..820f209 --- /dev/null +++ b/src/lib/components/ui/slider/index.ts @@ -0,0 +1,7 @@ +import Root from "./slider.svelte"; + +export { + Root, + // + Root as Slider, +}; diff --git a/src/lib/components/ui/slider/slider.svelte b/src/lib/components/ui/slider/slider.svelte new file mode 100644 index 0000000..932a9ff --- /dev/null +++ b/src/lib/components/ui/slider/slider.svelte @@ -0,0 +1,27 @@ + + + + + + + {#each thumbs as thumb} + + {/each} + diff --git a/src/lib/components/ui/sonner/index.ts b/src/lib/components/ui/sonner/index.ts new file mode 100644 index 0000000..1ad9f4a --- /dev/null +++ b/src/lib/components/ui/sonner/index.ts @@ -0,0 +1 @@ +export { default as Toaster } from "./sonner.svelte"; diff --git a/src/lib/components/ui/sonner/sonner.svelte b/src/lib/components/ui/sonner/sonner.svelte new file mode 100644 index 0000000..7d5b2f1 --- /dev/null +++ b/src/lib/components/ui/sonner/sonner.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/switch/index.ts b/src/lib/components/ui/switch/index.ts new file mode 100644 index 0000000..f5533db --- /dev/null +++ b/src/lib/components/ui/switch/index.ts @@ -0,0 +1,7 @@ +import Root from "./switch.svelte"; + +export { + Root, + // + Root as Switch, +}; diff --git a/src/lib/components/ui/switch/switch.svelte b/src/lib/components/ui/switch/switch.svelte new file mode 100644 index 0000000..6ec7961 --- /dev/null +++ b/src/lib/components/ui/switch/switch.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/src/lib/components/ui/table/index.ts b/src/lib/components/ui/table/index.ts new file mode 100644 index 0000000..14695c8 --- /dev/null +++ b/src/lib/components/ui/table/index.ts @@ -0,0 +1,28 @@ +import Root from "./table.svelte"; +import Body from "./table-body.svelte"; +import Caption from "./table-caption.svelte"; +import Cell from "./table-cell.svelte"; +import Footer from "./table-footer.svelte"; +import Head from "./table-head.svelte"; +import Header from "./table-header.svelte"; +import Row from "./table-row.svelte"; + +export { + Root, + Body, + Caption, + Cell, + Footer, + Head, + Header, + Row, + // + Root as Table, + Body as TableBody, + Caption as TableCaption, + Cell as TableCell, + Footer as TableFooter, + Head as TableHead, + Header as TableHeader, + Row as TableRow, +}; diff --git a/src/lib/components/ui/table/table-body.svelte b/src/lib/components/ui/table/table-body.svelte new file mode 100644 index 0000000..697deda --- /dev/null +++ b/src/lib/components/ui/table/table-body.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/table/table-caption.svelte b/src/lib/components/ui/table/table-caption.svelte new file mode 100644 index 0000000..ac0b827 --- /dev/null +++ b/src/lib/components/ui/table/table-caption.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/table/table-cell.svelte b/src/lib/components/ui/table/table-cell.svelte new file mode 100644 index 0000000..6f8eb89 --- /dev/null +++ b/src/lib/components/ui/table/table-cell.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/src/lib/components/ui/table/table-footer.svelte b/src/lib/components/ui/table/table-footer.svelte new file mode 100644 index 0000000..d3d36e5 --- /dev/null +++ b/src/lib/components/ui/table/table-footer.svelte @@ -0,0 +1,13 @@ + + + + + diff --git a/src/lib/components/ui/table/table-head.svelte b/src/lib/components/ui/table/table-head.svelte new file mode 100644 index 0000000..7e96384 --- /dev/null +++ b/src/lib/components/ui/table/table-head.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/lib/components/ui/table/table-header.svelte b/src/lib/components/ui/table/table-header.svelte new file mode 100644 index 0000000..4e54759 --- /dev/null +++ b/src/lib/components/ui/table/table-header.svelte @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/lib/components/ui/table/table-row.svelte b/src/lib/components/ui/table/table-row.svelte new file mode 100644 index 0000000..9c0ce02 --- /dev/null +++ b/src/lib/components/ui/table/table-row.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/src/lib/components/ui/table/table.svelte b/src/lib/components/ui/table/table.svelte new file mode 100644 index 0000000..0ebac71 --- /dev/null +++ b/src/lib/components/ui/table/table.svelte @@ -0,0 +1,15 @@ + + +
    + + +
    +
    diff --git a/src/lib/components/ui/tabs/index.ts b/src/lib/components/ui/tabs/index.ts new file mode 100644 index 0000000..f1ab372 --- /dev/null +++ b/src/lib/components/ui/tabs/index.ts @@ -0,0 +1,18 @@ +import { Tabs as TabsPrimitive } from "bits-ui"; +import Content from "./tabs-content.svelte"; +import List from "./tabs-list.svelte"; +import Trigger from "./tabs-trigger.svelte"; + +const Root = TabsPrimitive.Root; + +export { + Root, + Content, + List, + Trigger, + // + Root as Tabs, + Content as TabsContent, + List as TabsList, + Trigger as TabsTrigger, +}; diff --git a/src/lib/components/ui/tabs/tabs-content.svelte b/src/lib/components/ui/tabs/tabs-content.svelte new file mode 100644 index 0000000..93b6ac4 --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-content.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/ui/tabs/tabs-list.svelte b/src/lib/components/ui/tabs/tabs-list.svelte new file mode 100644 index 0000000..8d8ace2 --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-list.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/lib/components/ui/tabs/tabs-trigger.svelte b/src/lib/components/ui/tabs/tabs-trigger.svelte new file mode 100644 index 0000000..a74fdd7 --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-trigger.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/src/lib/components/ui/textarea/index.ts b/src/lib/components/ui/textarea/index.ts new file mode 100644 index 0000000..6eb6ba3 --- /dev/null +++ b/src/lib/components/ui/textarea/index.ts @@ -0,0 +1,28 @@ +import Root from "./textarea.svelte"; + +type FormTextareaEvent = T & { + currentTarget: EventTarget & HTMLTextAreaElement; +}; + +type TextareaEvents = { + blur: FormTextareaEvent; + change: FormTextareaEvent; + click: FormTextareaEvent; + focus: FormTextareaEvent; + keydown: FormTextareaEvent; + keypress: FormTextareaEvent; + keyup: FormTextareaEvent; + mouseover: FormTextareaEvent; + mouseenter: FormTextareaEvent; + mouseleave: FormTextareaEvent; + paste: FormTextareaEvent; + input: FormTextareaEvent; +}; + +export { + Root, + // + Root as Textarea, + type TextareaEvents, + type FormTextareaEvent, +}; diff --git a/src/lib/components/ui/textarea/textarea.svelte b/src/lib/components/ui/textarea/textarea.svelte new file mode 100644 index 0000000..99f043f --- /dev/null +++ b/src/lib/components/ui/textarea/textarea.svelte @@ -0,0 +1,38 @@ + + + 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..053ebbc --- /dev/null +++ b/src/lib/components/ui/toggle-group/index.ts @@ -0,0 +1,23 @@ +import type { VariantProps } from "tailwind-variants"; +import { getContext, setContext } from "svelte"; +import Root from "./toggle-group.svelte"; +import Item from "./toggle-group-item.svelte"; +import type { toggleVariants } from "$lib/components/ui/toggle/index.js"; + +export type ToggleVariants = VariantProps; + +export function setToggleGroupCtx(props: ToggleVariants) { + setContext("toggleGroup", props); +} + +export function getToggleGroupCtx() { + return getContext("toggleGroup"); +} + +export { + Root, + Item, + // + 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..aec22a0 --- /dev/null +++ b/src/lib/components/ui/toggle-group/toggle-group-item.svelte @@ -0,0 +1,31 @@ + + + + + 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..dd5e7ef --- /dev/null +++ b/src/lib/components/ui/toggle-group/toggle-group.svelte @@ -0,0 +1,30 @@ + + + + + diff --git a/src/lib/components/ui/toggle/index.ts b/src/lib/components/ui/toggle/index.ts new file mode 100644 index 0000000..1ab27ca --- /dev/null +++ b/src/lib/components/ui/toggle/index.ts @@ -0,0 +1,31 @@ +import { type VariantProps, tv } from "tailwind-variants"; +import Root from "./toggle.svelte"; + +export const toggleVariants = tv({ + base: "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground", + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground", + }, + size: { + default: "h-10 px-3", + sm: "h-9 px-2.5", + lg: "h-11 px-5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, +}); + +export type Variant = VariantProps["variant"]; +export type Size = VariantProps["size"]; + +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..f56ad97 --- /dev/null +++ b/src/lib/components/ui/toggle/toggle.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/src/lib/components/ui/tooltip/index.ts b/src/lib/components/ui/tooltip/index.ts new file mode 100644 index 0000000..7d0444d --- /dev/null +++ b/src/lib/components/ui/tooltip/index.ts @@ -0,0 +1,15 @@ +import { Tooltip as TooltipPrimitive } from "bits-ui"; +import Content from "./tooltip-content.svelte"; + +const Root = TooltipPrimitive.Root; +const Trigger = TooltipPrimitive.Trigger; + +export { + Root, + Trigger, + Content, + // + Root as Tooltip, + Content as TooltipContent, + Trigger as TooltipTrigger, +}; 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..1629103 --- /dev/null +++ b/src/lib/components/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/src/lib/constants/status-codes.ts b/src/lib/constants/status-codes.ts new file mode 100644 index 0000000..2e44e8d --- /dev/null +++ b/src/lib/constants/status-codes.ts @@ -0,0 +1,357 @@ +// Taken from https://github.com/prettymuchbryce/http-status-codes/blob/master/src/status-codes.ts +export enum StatusCodes { + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.2.1 + * + * This interim response indicates that everything so far is OK and that the client should continue with the request or ignore it if it is already finished. + */ + CONTINUE = 100, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.2.2 + * + * This code is sent in response to an Upgrade request header by the client, and indicates the protocol the server is switching too. + */ + SWITCHING_PROTOCOLS = 101, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.1 + * + * This code indicates that the server has received and is processing the request, but no response is available yet. + */ + PROCESSING = 102, + /** + * Official Documentation @ https://www.rfc-editor.org/rfc/rfc8297#page-3 + * + * This code indicates to the client that the server is likely to send a final response with the header fields included in the informational response. + */ + EARLY_HINTS = 103, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.1 + * + * The request has succeeded. The meaning of a success varies depending on the HTTP method: + * GET: The resource has been fetched and is transmitted in the message body. + * HEAD: The entity headers are in the message body. + * POST: The resource describing the result of the action is transmitted in the message body. + * TRACE: The message body contains the request message as received by the server + */ + OK = 200, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.2 + * + * The request has succeeded and a new resource has been created as a result of it. This is typically the response sent after a PUT request. + */ + CREATED = 201, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.3 + * + * The request has been received but not yet acted upon. It is non-committal, meaning that there is no way in HTTP to later send an asynchronous response indicating the outcome of processing the request. It is intended for cases where another process or server handles the request, or for batch processing. + */ + ACCEPTED = 202, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.4 + * + * This response code means returned meta-information set is not exact set as available from the origin server, but collected from a local or a third party copy. Except this condition, 200 OK response should be preferred instead of this response. + */ + NON_AUTHORITATIVE_INFORMATION = 203, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.5 + * + * There is no content to send for this request, but the headers may be useful. The user-agent may update its cached headers for this resource with the new ones. + */ + NO_CONTENT = 204, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.6 + * + * This response code is sent after accomplishing request to tell user agent reset document view which sent this request. + */ + RESET_CONTENT = 205, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7233#section-4.1 + * + * This response code is used because of range header sent by the client to separate download into multiple streams. + */ + PARTIAL_CONTENT = 206, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.2 + * + * A Multi-Status response conveys information about multiple resources in situations where multiple status codes might be appropriate. + */ + MULTI_STATUS = 207, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.4.1 + * + * The request has more than one possible responses. User-agent or user should choose one of them. There is no standardized way to choose one of the responses. + */ + MULTIPLE_CHOICES = 300, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.4.2 + * + * This response code means that URI of requested resource has been changed. Probably, new URI would be given in the response. + */ + MOVED_PERMANENTLY = 301, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.4.3 + * + * This response code means that URI of requested resource has been changed temporarily. New changes in the URI might be made in the future. Therefore, this same URI should be used by the client in future requests. + */ + MOVED_TEMPORARILY = 302, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.4.4 + * + * Server sent this response to directing client to get requested resource to another URI with an GET request. + */ + SEE_OTHER = 303, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7232#section-4.1 + * + * This is used for caching purposes. It is telling to client that response has not been modified. So, client can continue to use same cached version of response. + */ + NOT_MODIFIED = 304, + /** + * @deprecated + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.4.6 + * + * Was defined in a previous version of the HTTP specification to indicate that a requested response must be accessed by a proxy. It has been deprecated due to security concerns regarding in-band configuration of a proxy. + */ + USE_PROXY = 305, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.4.7 + * + * Server sent this response to directing client to get requested resource to another URI with same method that used prior request. This has the same semantic than the 302 Found HTTP response code, with the exception that the user agent must not change the HTTP method used: if a POST was used in the first request, a POST must be used in the second request. + */ + TEMPORARY_REDIRECT = 307, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7538#section-3 + * + * This means that the resource is now permanently located at another URI, specified by the Location: HTTP Response header. This has the same semantics as the 301 Moved Permanently HTTP response code, with the exception that the user agent must not change the HTTP method used: if a POST was used in the first request, a POST must be used in the second request. + */ + PERMANENT_REDIRECT = 308, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.1 + * + * This response means that server could not understand the request due to invalid syntax. + */ + BAD_REQUEST = 400, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7235#section-3.1 + * + * Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. + */ + UNAUTHORIZED = 401, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.2 + * + * This response code is reserved for future use. Initial aim for creating this code was using it for digital payment systems however this is not used currently. + */ + PAYMENT_REQUIRED = 402, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.3 + * + * The client does not have access rights to the content, i.e. they are unauthorized, so server is rejecting to give proper response. Unlike 401, the client's identity is known to the server. + */ + FORBIDDEN = 403, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.4 + * + * The server can not find requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 to hide the existence of a resource from an unauthorized client. This response code is probably the most famous one due to its frequent occurence on the web. + */ + NOT_FOUND = 404, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.5 + * + * The request method is known by the server but has been disabled and cannot be used. For example, an API may forbid DELETE-ing a resource. The two mandatory methods, GET and HEAD, must never be disabled and should not return this error code. + */ + METHOD_NOT_ALLOWED = 405, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.6 + * + * This response is sent when the web server, after performing server-driven content negotiation, doesn't find any content following the criteria given by the user agent. + */ + NOT_ACCEPTABLE = 406, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7235#section-3.2 + * + * This is similar to 401 but authentication is needed to be done by a proxy. + */ + PROXY_AUTHENTICATION_REQUIRED = 407, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.7 + * + * This response is sent on an idle connection by some servers, even without any previous request by the client. It means that the server would like to shut down this unused connection. This response is used much more since some browsers, like Chrome, Firefox 27+, or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also note that some servers merely shut down the connection without sending this message. + */ + REQUEST_TIMEOUT = 408, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.8 + * + * This response is sent when a request conflicts with the current state of the server. + */ + CONFLICT = 409, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.9 + * + * This response would be sent when the requested content has been permenantly deleted from server, with no forwarding address. Clients are expected to remove their caches and links to the resource. The HTTP specification intends this status code to be used for "limited-time, promotional services". APIs should not feel compelled to indicate resources that have been deleted with this status code. + */ + GONE = 410, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.10 + * + * The server rejected the request because the Content-Length header field is not defined and the server requires it. + */ + LENGTH_REQUIRED = 411, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7232#section-4.2 + * + * The client has indicated preconditions in its headers which the server does not meet. + */ + PRECONDITION_FAILED = 412, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.11 + * + * Request entity is larger than limits defined by server; the server might close the connection or return an Retry-After header field. + */ + REQUEST_TOO_LONG = 413, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.12 + * + * The URI requested by the client is longer than the server is willing to interpret. + */ + REQUEST_URI_TOO_LONG = 414, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.13 + * + * The media format of the requested data is not supported by the server, so the server is rejecting the request. + */ + UNSUPPORTED_MEDIA_TYPE = 415, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7233#section-4.4 + * + * The range specified by the Range header field in the request can't be fulfilled; it's possible that the range is outside the size of the target URI's data. + */ + REQUESTED_RANGE_NOT_SATISFIABLE = 416, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.14 + * + * This response code means the expectation indicated by the Expect request header field can't be met by the server. + */ + EXPECTATION_FAILED = 417, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2324#section-2.3.2 + * + * Any attempt to brew coffee with a teapot should result in the error code "418 I'm a teapot". The resulting entity body MAY be short and stout. + */ + IM_A_TEAPOT = 418, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.6 + * + * The 507 (Insufficient Storage) status code means the method could not be performed on the resource because the server is unable to store the representation needed to successfully complete the request. This condition is considered to be temporary. If the request which received this status code was the result of a user action, the request MUST NOT be repeated until it is requested by a separate user action. + */ + INSUFFICIENT_SPACE_ON_RESOURCE = 419, + /** + * @deprecated + * Official Documentation @ https://tools.ietf.org/rfcdiff?difftype=--hwdiff&url2=draft-ietf-webdav-protocol-06.txt + * + * A deprecated response used by the Spring Framework when a method has failed. + */ + METHOD_FAILURE = 420, + /** + * Official Documentation @ https://datatracker.ietf.org/doc/html/rfc7540#section-9.1.2 + * + * Defined in the specification of HTTP/2 to indicate that a server is not able to produce a response for the combination of scheme and authority that are included in the request URI. + */ + MISDIRECTED_REQUEST = 421, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.3 + * + * The request was well-formed but was unable to be followed due to semantic errors. + */ + UNPROCESSABLE_ENTITY = 422, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.4 + * + * The resource that is being accessed is locked. + */ + LOCKED = 423, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.5 + * + * The request failed due to failure of a previous request. + */ + FAILED_DEPENDENCY = 424, + /** + * Official Documentation @ https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.15 + * + * The server refuses to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol. + */ + UPGRADE_REQUIRED = 426, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc6585#section-3 + * + * The origin server requires the request to be conditional. Intended to prevent the 'lost update' problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict. + */ + PRECONDITION_REQUIRED = 428, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc6585#section-4 + * + * The user has sent too many requests in a given amount of time ("rate limiting"). + */ + TOO_MANY_REQUESTS = 429, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc6585#section-5 + * + * The server is unwilling to process the request because its header fields are too large. The request MAY be resubmitted after reducing the size of the request header fields. + */ + REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7725 + * + * The user-agent requested a resource that cannot legally be provided, such as a web page censored by a government. + */ + UNAVAILABLE_FOR_LEGAL_REASONS = 451, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.1 + * + * The server encountered an unexpected condition that prevented it from fulfilling the request. + */ + INTERNAL_SERVER_ERROR = 500, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.2 + * + * The request method is not supported by the server and cannot be handled. The only methods that servers are required to support (and therefore that must not return this code) are GET and HEAD. + */ + NOT_IMPLEMENTED = 501, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.3 + * + * This error response means that the server, while working as a gateway to get a response needed to handle the request, got an invalid response. + */ + BAD_GATEWAY = 502, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.4 + * + * The server is not ready to handle the request. Common causes are a server that is down for maintenance or that is overloaded. Note that together with this response, a user-friendly page explaining the problem should be sent. This responses should be used for temporary conditions and the Retry-After: HTTP header should, if possible, contain the estimated time before the recovery of the service. The webmaster must also take care about the caching-related headers that are sent along with this response, as these temporary condition responses should usually not be cached. + */ + SERVICE_UNAVAILABLE = 503, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.5 + * + * This error response is given when the server is acting as a gateway and cannot get a response in time. + */ + GATEWAY_TIMEOUT = 504, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.6 + * + * The HTTP version used in the request is not supported by the server. + */ + HTTP_VERSION_NOT_SUPPORTED = 505, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.6 + * + * The server has an internal configuration error: the chosen variant resource is configured to engage in transparent content negotiation itself, and is therefore not a proper end point in the negotiation process. + */ + INSUFFICIENT_STORAGE = 507, + /** + * Official Documentation @ https://tools.ietf.org/html/rfc6585#section-6 + * + * The 511 status code indicates that the client needs to authenticate to gain network access. + */ + NETWORK_AUTHENTICATION_REQUIRED = 511 +} \ No newline at end of file diff --git a/src/lib/server/api/common/config.ts b/src/lib/server/api/common/config.ts new file mode 100644 index 0000000..df45a0b --- /dev/null +++ b/src/lib/server/api/common/config.ts @@ -0,0 +1,22 @@ +import * as envs from '$env/static/private'; +import type { Config } from './types/config'; + +export const config: Config = { + isProduction: envs.NODE_ENV === 'production', + api: { + origin: envs.ORIGIN, + }, + storage: { + accessKey: envs.STORAGE_ACCESS_KEY, + secretKey: envs.STORAGE_SECRET_KEY, + bucket: envs.STORAGE_BUCKET, + url: envs.STORAGE_URL + }, + postgres: { + url: envs.DATABASE_URL + }, + redis: { + url: envs.REDIS_URL + } +} + diff --git a/src/lib/server/api/common/exceptions.ts b/src/lib/server/api/common/exceptions.ts new file mode 100644 index 0000000..fee54c4 --- /dev/null +++ b/src/lib/server/api/common/exceptions.ts @@ -0,0 +1,26 @@ +import { StatusCodes } from '$lib/constants/status-codes'; +import { HTTPException } from 'hono/http-exception'; + +export function TooManyRequests(message: string = 'Too many requests') { + return new HTTPException(StatusCodes.TOO_MANY_REQUESTS, { message }); +} + +export function Forbidden(message: string = 'Forbidden') { + return new HTTPException(StatusCodes.FORBIDDEN, { message }); +} + +export function Unauthorized(message: string = 'Unauthorized') { + return new HTTPException(StatusCodes.UNAUTHORIZED, { message }); +} + +export function NotFound(message: string = 'Not Found') { + return new HTTPException(StatusCodes.NOT_FOUND, { message }); +} + +export function BadRequest(message: string = 'Bad Request') { + return new HTTPException(StatusCodes.BAD_REQUEST, { message }); +} + +export function InternalError(message: string = 'Internal Error') { + return new HTTPException(StatusCodes.INTERNAL_SERVER_ERROR, { message }); +} diff --git a/src/lib/server/api/common/types/async-service.ts b/src/lib/server/api/common/types/async-service.ts new file mode 100644 index 0000000..d85364c --- /dev/null +++ b/src/lib/server/api/common/types/async-service.ts @@ -0,0 +1,3 @@ +export abstract class AsyncService { + async init(): Promise { } +} \ No newline at end of file diff --git a/src/lib/server/api/common/types/config.ts b/src/lib/server/api/common/types/config.ts new file mode 100644 index 0000000..7df400b --- /dev/null +++ b/src/lib/server/api/common/types/config.ts @@ -0,0 +1,26 @@ +export interface Config { + isProduction: boolean; + api: ApiConfig; + storage: StorageConfig; + redis: RedisConfig; + postgres: PostgresConfig; +} + +interface ApiConfig { + origin: string; +} + +interface StorageConfig { + accessKey: string; + secretKey: string; + bucket: string; + url: string; +} + +interface RedisConfig { + url: string; +} + +interface PostgresConfig { + url: string; +} \ No newline at end of file diff --git a/src/lib/server/api/common/types/controller.ts b/src/lib/server/api/common/types/controller.ts new file mode 100644 index 0000000..d1b26bf --- /dev/null +++ b/src/lib/server/api/common/types/controller.ts @@ -0,0 +1,11 @@ +import { Hono } from "hono"; +import type { HonoTypes } from "./hono"; +import type { BlankSchema } from "hono/types"; + +export abstract class Controler { + protected readonly controller: Hono; + constructor() { + this.controller = new Hono(); + } + abstract routes(): Hono; +} \ No newline at end of file diff --git a/src/lib/server/api/common/types/email.ts b/src/lib/server/api/common/types/email.ts new file mode 100644 index 0000000..520bf17 --- /dev/null +++ b/src/lib/server/api/common/types/email.ts @@ -0,0 +1,4 @@ +export interface Email { + subject(): string + html(): string; +} diff --git a/src/lib/server/api/common/types/hono.ts b/src/lib/server/api/common/types/hono.ts new file mode 100644 index 0000000..401e8d7 --- /dev/null +++ b/src/lib/server/api/common/types/hono.ts @@ -0,0 +1,14 @@ +import type { Promisify, RateLimitInfo } from 'hono-rate-limiter'; +import type { Session, User } from 'lucia'; + +export type HonoTypes = { + Variables: { + session: Session | null; + user: User | null; + rateLimit: RateLimitInfo; + rateLimitStore: { + getKey?: (key: string) => Promisify; + resetKey: (key: string) => Promisify; + }; + }; +}; diff --git a/src/lib/server/api/common/types/mailer.ts b/src/lib/server/api/common/types/mailer.ts new file mode 100644 index 0000000..9b910da --- /dev/null +++ b/src/lib/server/api/common/types/mailer.ts @@ -0,0 +1,3 @@ +interface INotifier { + sendEmail(): any; +} diff --git a/src/lib/server/api/common/utils/repository.ts b/src/lib/server/api/common/utils/repository.ts new file mode 100644 index 0000000..b7dbd82 --- /dev/null +++ b/src/lib/server/api/common/utils/repository.ts @@ -0,0 +1,14 @@ +import { HTTPException } from "hono/http-exception"; + +export const takeFirst = (values: T[]): T | null => { + if (values.length === 0) return null; + return values[0]!; +}; + +export const takeFirstOrThrow = (values: T[]): T => { + if (values.length === 0) + throw new HTTPException(404, { + message: 'Resource not found' + }); + return values[0]!; +}; \ No newline at end of file diff --git a/src/lib/server/api/common/utils/table.ts b/src/lib/server/api/common/utils/table.ts new file mode 100644 index 0000000..361a6d0 --- /dev/null +++ b/src/lib/server/api/common/utils/table.ts @@ -0,0 +1,30 @@ +import { timestamp } from 'drizzle-orm/pg-core'; +import { customType } from 'drizzle-orm/pg-core'; + +export const citext = customType<{ data: string }>({ + dataType() { + return 'citext'; + } +}); + +export const cuid2 = customType<{ data: string }>({ + dataType() { + return 'text'; + } +}); + +export const timestamps = { + createdAt: timestamp('created_at', { + mode: 'date', + withTimezone: true + }) + .notNull() + .defaultNow(), + updatedAt: timestamp('updated_at', { + mode: 'date', + withTimezone: true + }) + .notNull() + .defaultNow() + .$onUpdate(() => new Date()) +}; diff --git a/src/lib/server/api/controllers/iam.controller.ts b/src/lib/server/api/controllers/iam.controller.ts new file mode 100644 index 0000000..4b45dac --- /dev/null +++ b/src/lib/server/api/controllers/iam.controller.ts @@ -0,0 +1,79 @@ +import { setCookie } from 'hono/cookie'; +import { inject, injectable } from 'tsyringe'; +import { zValidator } from '@hono/zod-validator'; +import { limiter } from '../middlewares/rate-limiter.middlware'; +import { requireAuth } from '../middlewares/require-auth.middleware'; +import { Controler } from '../common/types/controller'; +import { updateEmailDto } from '$lib/server/api/dtos/update-email.dto'; +import { verifyEmailDto } from '$lib/server/api/dtos/verify-email.dto'; +import { LuciaService } from '../services/lucia.service'; +import { AuthenticationService } from '../services/authentication.service'; +import { EmailVerificationService } from '../services/email-verification.service'; +import { loginDto } from '../dtos/login.dto'; +import { verifyLoginDto } from '../dtos/verify-login.dto'; + +@injectable() +export class IamController extends Controler { + constructor( + @inject(AuthenticationService) private authenticationService: AuthenticationService, + @inject(EmailVerificationService) private emailVerificationService: EmailVerificationService, + @inject(LuciaService) private luciaService: LuciaService, + ) { + super(); + } + + routes() { + return this.controller + .get('/me', async (c) => { + const user = c.var.user; + return c.json({ user: user }); + }) + .post('/login', zValidator('json', loginDto), limiter({ limit: 10, minutes: 60 }), async (c) => { + const { email } = c.req.valid('json'); + await this.authenticationService.createLoginRequest({ email }); + return c.json({ message: 'Verification email sent' }); + }) + .post('/login/verify', zValidator('json', verifyLoginDto), limiter({ limit: 10, minutes: 60 }), async (c) => { + const { email, token } = c.req.valid('json'); + const session = await this.authenticationService.verifyLoginRequest({ email, token }); + const sessionCookie = this.luciaService.lucia.createSessionCookie(session.id); + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: sessionCookie.attributes.maxAge, + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires + }); + return c.json({ message: 'ok' }); + }) + .patch('/email', requireAuth, zValidator('json', updateEmailDto), limiter({ limit: 10, minutes: 60 }), async (c) => { + const json = c.req.valid('json'); + await this.emailVerificationService.create(c.var.user.id, json.email); + return c.json({ message: 'Verification email sent' }); + }) + // this could also be named to use custom methods, aka /email#verify + // https://cloud.google.com/apis/design/custom_methods + .post('/email/verify', requireAuth, zValidator('json', verifyEmailDto), limiter({ limit: 10, minutes: 60 }), async (c) => { + const json = c.req.valid('json'); + await this.emailVerificationService.verify(c.var.user.id, json.token); + return c.json({ message: 'Verified and updated' }); + }) + .post('/logout', requireAuth, async (c) => { + const sessionId = c.var.session.id; + await this.authenticationService.logout(sessionId); + const sessionCookie = this.luciaService.lucia.createBlankSessionCookie(); + setCookie(c, sessionCookie.name, sessionCookie.value, { + path: sessionCookie.attributes.path, + maxAge: sessionCookie.attributes.maxAge, + domain: sessionCookie.attributes.domain, + sameSite: sessionCookie.attributes.sameSite as any, + secure: sessionCookie.attributes.secure, + httpOnly: sessionCookie.attributes.httpOnly, + expires: sessionCookie.attributes.expires + }); + return c.json({ status: 'success' }); + }) + } +} diff --git a/src/lib/server/api/databases/postgres/migrations/0000_clear_paper_doll.sql b/src/lib/server/api/databases/postgres/migrations/0000_clear_paper_doll.sql new file mode 100644 index 0000000..7903444 --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/0000_clear_paper_doll.sql @@ -0,0 +1,50 @@ +CREATE EXTENSION IF NOT EXISTS "citext"; + +CREATE TABLE IF NOT EXISTS "email_verifications" ( + "id" text PRIMARY KEY NOT NULL, + "hashed_token" text NOT NULL, + "user_id" text NOT NULL, + "requested_email" text NOT NULL, + "expires_at" timestamp with time zone NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "email_verifications_user_id_unique" UNIQUE("user_id") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "login_requests" ( + "id" text PRIMARY KEY NOT NULL, + "hashed_token" text NOT NULL, + "email" text NOT NULL, + "expires_at" timestamp with time zone NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "login_requests_email_unique" UNIQUE("email") +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "sessions" ( + "id" text PRIMARY KEY NOT NULL, + "user_id" text NOT NULL, + "expires_at" timestamp with time zone NOT NULL +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "users" ( + "id" text PRIMARY KEY NOT NULL, + "avatar" text, + "email" "citext" NOT NULL, + "verified" boolean DEFAULT false NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "users_email_unique" UNIQUE("email") +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "email_verifications" ADD CONSTRAINT "email_verifications_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/src/lib/server/api/databases/postgres/migrations/0001_gifted_james_howlett.sql b/src/lib/server/api/databases/postgres/migrations/0001_gifted_james_howlett.sql new file mode 100644 index 0000000..057b264 --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/0001_gifted_james_howlett.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS "files" ( + "id" text PRIMARY KEY NOT NULL, + "key" text NOT NULL, + "size" bigint NOT NULL, + "content_type" text NOT NULL, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "users" ADD CONSTRAINT "users_avatar_files_id_fk" FOREIGN KEY ("avatar") REFERENCES "public"."files"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/src/lib/server/api/databases/postgres/migrations/0002_sharp_risque.sql b/src/lib/server/api/databases/postgres/migrations/0002_sharp_risque.sql new file mode 100644 index 0000000..d1f8ae0 --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/0002_sharp_risque.sql @@ -0,0 +1,15 @@ +ALTER TABLE "email_verifications" DROP CONSTRAINT "email_verifications_user_id_users_id_fk"; +--> statement-breakpoint +ALTER TABLE "sessions" DROP CONSTRAINT "sessions_user_id_users_id_fk"; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "email_verifications" ADD CONSTRAINT "email_verifications_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "sessions" ADD CONSTRAINT "sessions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/src/lib/server/api/databases/postgres/migrations/meta/0000_snapshot.json b/src/lib/server/api/databases/postgres/migrations/meta/0000_snapshot.json new file mode 100644 index 0000000..b758ed2 --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/meta/0000_snapshot.json @@ -0,0 +1,247 @@ +{ + "id": "7c8066fe-53c3-4fbb-b700-34ae02d25480", + "prevId": "00000000-0000-0000-0000-000000000000", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.email_verifications": { + "name": "email_verifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "hashed_token": { + "name": "hashed_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requested_email": { + "name": "requested_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "email_verifications_user_id_users_id_fk": { + "name": "email_verifications_user_id_users_id_fk", + "tableFrom": "email_verifications", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_verifications_user_id_unique": { + "name": "email_verifications_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + } + }, + "public.login_requests": { + "name": "login_requests", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "hashed_token": { + "name": "hashed_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "login_requests_email_unique": { + "name": "login_requests_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "citext", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + } + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/lib/server/api/databases/postgres/migrations/meta/0001_snapshot.json b/src/lib/server/api/databases/postgres/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..a1c5423 --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/meta/0001_snapshot.json @@ -0,0 +1,315 @@ +{ + "id": "00340fa1-eeb1-41d9-bbe3-972ed52f7ca1", + "prevId": "7c8066fe-53c3-4fbb-b700-34ae02d25480", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.email_verifications": { + "name": "email_verifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "hashed_token": { + "name": "hashed_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requested_email": { + "name": "requested_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "email_verifications_user_id_users_id_fk": { + "name": "email_verifications_user_id_users_id_fk", + "tableFrom": "email_verifications", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_verifications_user_id_unique": { + "name": "email_verifications_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "checkConstraints": {} + }, + "public.files": { + "name": "files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "public.login_requests": { + "name": "login_requests", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "hashed_token": { + "name": "hashed_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "login_requests_email_unique": { + "name": "login_requests_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "checkConstraints": {} + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "citext", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "users_avatar_files_id_fk": { + "name": "users_avatar_files_id_fk", + "tableFrom": "users", + "tableTo": "files", + "columnsFrom": [ + "avatar" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "checkConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/lib/server/api/databases/postgres/migrations/meta/0002_snapshot.json b/src/lib/server/api/databases/postgres/migrations/meta/0002_snapshot.json new file mode 100644 index 0000000..1f4e16f --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/meta/0002_snapshot.json @@ -0,0 +1,315 @@ +{ + "id": "5796b846-6715-463d-8a8b-15b8dad25d10", + "prevId": "00340fa1-eeb1-41d9-bbe3-972ed52f7ca1", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.email_verifications": { + "name": "email_verifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "hashed_token": { + "name": "hashed_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "requested_email": { + "name": "requested_email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "email_verifications_user_id_users_id_fk": { + "name": "email_verifications_user_id_users_id_fk", + "tableFrom": "email_verifications", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_verifications_user_id_unique": { + "name": "email_verifications_user_id_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id" + ] + } + }, + "checkConstraints": {} + }, + "public.files": { + "name": "files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "bigint", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "public.login_requests": { + "name": "login_requests", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "hashed_token": { + "name": "hashed_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "login_requests_email_unique": { + "name": "login_requests_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "checkConstraints": {} + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "citext", + "primaryKey": false, + "notNull": true + }, + "verified": { + "name": "verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "users_avatar_files_id_fk": { + "name": "users_avatar_files_id_fk", + "tableFrom": "users", + "tableTo": "files", + "columnsFrom": [ + "avatar" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + } + }, + "checkConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/src/lib/server/api/databases/postgres/migrations/meta/_journal.json b/src/lib/server/api/databases/postgres/migrations/meta/_journal.json new file mode 100644 index 0000000..ac9cb27 --- /dev/null +++ b/src/lib/server/api/databases/postgres/migrations/meta/_journal.json @@ -0,0 +1,27 @@ +{ + "version": "7", + "dialect": "postgresql", + "entries": [ + { + "idx": 0, + "version": "7", + "when": 1722983304054, + "tag": "0000_clear_paper_doll", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1729196878223, + "tag": "0001_gifted_james_howlett", + "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1729199803558, + "tag": "0002_sharp_risque", + "breakpoints": true + } + ] +} \ No newline at end of file diff --git a/src/lib/server/api/databases/postgres/tables/email-verifications.table.ts b/src/lib/server/api/databases/postgres/tables/email-verifications.table.ts new file mode 100644 index 0000000..d007301 --- /dev/null +++ b/src/lib/server/api/databases/postgres/tables/email-verifications.table.ts @@ -0,0 +1,28 @@ +import { createId } from '@paralleldrive/cuid2'; +import { pgTable, text, timestamp } from 'drizzle-orm/pg-core'; +import { relations } from 'drizzle-orm'; +import { usersTable } from './users.table'; +import { timestamps } from '../../../common/utils/table'; + +export const emailVerificationsTable = pgTable('email_verifications', { + id: text('id') + .primaryKey() + .$defaultFn(() => createId()), + hashedToken: text('hashed_token').notNull(), + userId: text('user_id') + .notNull() + .references(() => usersTable.id, { onDelete: 'cascade' }).unique(), + requestedEmail: text('requested_email').notNull(), + expiresAt: timestamp('expires_at', { + mode: 'date', + withTimezone: true + }).notNull(), + ...timestamps +}); + +export const emailVerificationsRelations = relations(emailVerificationsTable, ({ one }) => ({ + user: one(usersTable, { + fields: [emailVerificationsTable.userId], + references: [usersTable.id] + }) +})); diff --git a/src/lib/server/api/databases/postgres/tables/files.table.ts b/src/lib/server/api/databases/postgres/tables/files.table.ts new file mode 100644 index 0000000..1ac79f2 --- /dev/null +++ b/src/lib/server/api/databases/postgres/tables/files.table.ts @@ -0,0 +1,12 @@ +import { bigint, pgTable, text } from "drizzle-orm/pg-core"; +import { cuid2, timestamps } from "../../../common/utils/table"; +import { createId } from "@paralleldrive/cuid2"; + +export const filesTable = pgTable('files', { + id: cuid2('id').primaryKey().$defaultFn(() => createId()), + key: text('key').notNull(), + size: bigint('size', { mode: 'bigint' }).notNull(), + contentType: text('content_type').notNull(), + ...timestamps +}); + diff --git a/src/lib/server/api/databases/postgres/tables/index.ts b/src/lib/server/api/databases/postgres/tables/index.ts new file mode 100644 index 0000000..d0d3ec0 --- /dev/null +++ b/src/lib/server/api/databases/postgres/tables/index.ts @@ -0,0 +1,4 @@ +export * from './sessions.table'; +export * from './users.table'; +export * from './login-requests.table'; +export * from './email-verifications.table'; diff --git a/src/lib/server/api/databases/postgres/tables/login-requests.table.ts b/src/lib/server/api/databases/postgres/tables/login-requests.table.ts new file mode 100644 index 0000000..afb2a24 --- /dev/null +++ b/src/lib/server/api/databases/postgres/tables/login-requests.table.ts @@ -0,0 +1,19 @@ +import { relations } from 'drizzle-orm'; +import { createId } from '@paralleldrive/cuid2'; +import { pgTable, text, timestamp } from 'drizzle-orm/pg-core'; +import { timestamps } from '../../../common/utils/table'; + +export const loginRequestsTable = pgTable('login_requests', { + id: text('id') + .primaryKey() + .$defaultFn(() => createId()), + hashedToken: text('hashed_token').notNull(), + email: text('email').notNull().unique(), + expiresAt: timestamp('expires_at', { + mode: 'date', + withTimezone: true + }).notNull(), + ...timestamps +}); + +export const loginRequestsRelations = relations(loginRequestsTable, () => ({})); diff --git a/src/lib/server/api/databases/postgres/tables/sessions.table.ts b/src/lib/server/api/databases/postgres/tables/sessions.table.ts new file mode 100644 index 0000000..24e6bde --- /dev/null +++ b/src/lib/server/api/databases/postgres/tables/sessions.table.ts @@ -0,0 +1,22 @@ +import { relations } from 'drizzle-orm'; +import { cuid2 } from '../../../common/utils/table'; +import { usersTable } from './users.table'; +import { pgTable, text, timestamp } from 'drizzle-orm/pg-core'; + +export const sessionsTable = pgTable('sessions', { + id: cuid2('id').primaryKey(), + userId: text('user_id') + .notNull() + .references(() => usersTable.id, { onDelete: 'cascade' }), + expiresAt: timestamp('expires_at', { + withTimezone: true, + mode: 'date' + }).notNull() +}); + +export const sessionsRelations = relations(sessionsTable, ({ one }) => ({ + user: one(usersTable, { + fields: [sessionsTable.userId], + references: [usersTable.id], + }), + })); \ No newline at end of file diff --git a/src/lib/server/api/databases/postgres/tables/users.table.ts b/src/lib/server/api/databases/postgres/tables/users.table.ts new file mode 100644 index 0000000..956539e --- /dev/null +++ b/src/lib/server/api/databases/postgres/tables/users.table.ts @@ -0,0 +1,30 @@ +import { relations } from 'drizzle-orm';; +import { createId } from '@paralleldrive/cuid2'; +import { sessionsTable } from './sessions.table'; +import { boolean, pgTable, text } from 'drizzle-orm/pg-core'; +import { emailVerificationsTable } from './email-verifications.table'; +import { citext, cuid2, timestamps } from '../../../common/utils/table'; +import { filesTable } from './files.table'; + + +export const usersTable = pgTable('users', { + id: text('id') + .primaryKey() + .$defaultFn(() => createId()), + avatarId: cuid2('avatar').references(() => filesTable.id), + email: citext('email').notNull().unique(), + verified: boolean('verified').notNull().default(false), + ...timestamps +}); + +export const usersRelations = relations(usersTable, ({ many, one }) => ({ + sessions: many(sessionsTable), + avatar: one(filesTable, { + fields: [usersTable.avatarId], + references: [filesTable.id] + }), + emailVerifications: one(emailVerificationsTable, { + fields: [usersTable.id], + references: [emailVerificationsTable.userId] + }) +})); diff --git a/src/lib/server/api/dtos/login.dto.ts b/src/lib/server/api/dtos/login.dto.ts new file mode 100644 index 0000000..3019e10 --- /dev/null +++ b/src/lib/server/api/dtos/login.dto.ts @@ -0,0 +1,7 @@ +import { z } from 'zod'; + +export const loginDto = z.object({ + email: z.string().email() +}); + +export type LoginDto = z.infer; diff --git a/src/lib/server/api/dtos/update-email.dto.ts b/src/lib/server/api/dtos/update-email.dto.ts new file mode 100644 index 0000000..4ab90a4 --- /dev/null +++ b/src/lib/server/api/dtos/update-email.dto.ts @@ -0,0 +1,6 @@ +import { z } from 'zod'; + +export const updateEmailDto = z.object({ + email: z.string().email() +}); +export type UpdateEmailDto = z.infer; diff --git a/src/lib/server/api/dtos/verify-email.dto.ts b/src/lib/server/api/dtos/verify-email.dto.ts new file mode 100644 index 0000000..bd1a395 --- /dev/null +++ b/src/lib/server/api/dtos/verify-email.dto.ts @@ -0,0 +1,7 @@ +import { z } from 'zod'; + +export const verifyEmailDto = z.object({ + token: z.string() +}); + +export type VerifyEmailDto = z.infer; diff --git a/src/lib/server/api/dtos/verify-login.dto.ts b/src/lib/server/api/dtos/verify-login.dto.ts new file mode 100644 index 0000000..c7385e3 --- /dev/null +++ b/src/lib/server/api/dtos/verify-login.dto.ts @@ -0,0 +1,8 @@ +import { z } from 'zod'; + +export const verifyLoginDto = z.object({ + email: z.string().email(), + token: z.string() +}); + +export type VerifyLoginDto = z.infer; diff --git a/src/lib/server/api/emails/email-change-notice.email.ts b/src/lib/server/api/emails/email-change-notice.email.ts new file mode 100644 index 0000000..b096787 --- /dev/null +++ b/src/lib/server/api/emails/email-change-notice.email.ts @@ -0,0 +1,32 @@ +import type { Email } from "../common/types/email" + +export class EmailChangeNoticeEmail implements Email { + constructor() { } + + subject(): string { + return 'Email Change Notice' + } + + html() { + return /*html*/ ` + + + + + Email Change Request + + +

    Email address change notice

    +

    + An update to your email address has been requested. If this is unexpected or you did not perform this action, please login and secure your account.

    + + + + ` + } +} diff --git a/src/lib/server/api/emails/login-verification.email.ts b/src/lib/server/api/emails/login-verification.email.ts new file mode 100644 index 0000000..61a0e3c --- /dev/null +++ b/src/lib/server/api/emails/login-verification.email.ts @@ -0,0 +1,39 @@ +import type { Email } from "../common/types/email" + +export class LoginVerificationEmail implements Email { + constructor(private readonly token: string) { } + + subject(): string { + return 'Email Verification' + } + + html() { + return /*html*/ ` + + + + + Message + + +

    Verify your email address

    +

    + Thanks for using example.com. We want to make sure it's really you. Please enter the following + verification code when prompted. If you don't have an exmaple.com an account, you can ignore + this message.

    +
    +

    Verification Code

    +

    ${this.token}

    +

    (This code is valid for 15 minutes)

    +
    + + + + ` + } +} diff --git a/src/lib/server/api/emails/welcome.email.ts b/src/lib/server/api/emails/welcome.email.ts new file mode 100644 index 0000000..bc973d3 --- /dev/null +++ b/src/lib/server/api/emails/welcome.email.ts @@ -0,0 +1,34 @@ +import type { Email } from "../common/types/email"; + +export class WelcomeEmail implements Email { + constructor() { } + + subject(): string { + return 'Welcome!' + } + + html(): string { + return /*html*/ ` + + + + + Message + + +

    Welcome to Example

    +

    + Thanks for using example.com. We want to make sure it's really you. Please enter the following + verification code when prompted. If you don't have an exmaple.com an account, you can ignore + this message.

    + + + + `; + } +} \ No newline at end of file diff --git a/src/lib/server/api/index.ts b/src/lib/server/api/index.ts new file mode 100644 index 0000000..4260474 --- /dev/null +++ b/src/lib/server/api/index.ts @@ -0,0 +1,41 @@ +import 'reflect-metadata'; +import { Hono } from 'hono'; +import { hc } from 'hono/client'; +import { container } from 'tsyringe'; +import { IamController } from './controllers/iam.controller'; +import { config } from './common/config'; +import { validateAuthSession, verifyOrigin } from './middlewares/auth.middleware'; +import { AuthCleanupJobs } from './jobs/auth-cleanup.job'; + +/* -------------------------------------------------------------------------- */ +/* App */ +/* -------------------------------------------------------------------------- */ +export const app = new Hono().basePath('/api'); + +/* -------------------------------------------------------------------------- */ +/* Global Middlewares */ +/* -------------------------------------------------------------------------- */ +app.use(verifyOrigin).use(validateAuthSession); + +/* -------------------------------------------------------------------------- */ +/* Routes */ +/* -------------------------------------------------------------------------- */ +const routes = app + .route('/iam', container.resolve(IamController).routes()) + +/* -------------------------------------------------------------------------- */ +/* Cron Jobs */ +/* -------------------------------------------------------------------------- */ +container.resolve(AuthCleanupJobs).deleteStaleEmailVerificationRequests(); +container.resolve(AuthCleanupJobs).deleteStaleLoginRequests(); + +/* -------------------------------------------------------------------------- */ +/* Exports */ +/* -------------------------------------------------------------------------- */ +const rpc = hc(config.api.origin); +export type ApiClient = typeof rpc; +export type ApiRoutes = typeof routes; + + + + diff --git a/src/lib/server/api/jobs/auth-cleanup.job.ts b/src/lib/server/api/jobs/auth-cleanup.job.ts new file mode 100644 index 0000000..a841e13 --- /dev/null +++ b/src/lib/server/api/jobs/auth-cleanup.job.ts @@ -0,0 +1,44 @@ +import { inject, injectable } from "tsyringe"; +import { JobsService } from "../services/jobs.service"; + +// Example on how to create a job that runs once a week at midnight on Sunday + +@injectable() +export class AuthCleanupJobs { + private queue; + + constructor(@inject(JobsService) private jobsService: JobsService) { + // create queue + this.queue = this.jobsService.createQueue('auth_cleanup') + + // register workers + this.worker(); + } + + async deleteStaleEmailVerificationRequests() { + this.queue.add('delete_stale_email_verifiactions', null, { + repeat: { + pattern: '0 0 * * 0' // Runs once a week at midnight on Sunday + } + }) + } + + async deleteStaleLoginRequests() { + this.queue.add('delete_stale_login_requests', null, { + repeat: { + pattern: '0 0 * * 0' // Runs once a week at midnight on Sunday + } + }) + } + + private async worker() { + return this.jobsService.createWorker(this.queue.name, async (job) => { + if (job.name === "delete_stale_email_verifiactions") { + // delete stale email verifications + } + if (job.name === "delete_stale_login_requests") { + // delete stale email verifications + } + }) + } +} \ No newline at end of file diff --git a/src/lib/server/api/middlewares/auth.middleware.ts b/src/lib/server/api/middlewares/auth.middleware.ts new file mode 100644 index 0000000..1fb1ed2 --- /dev/null +++ b/src/lib/server/api/middlewares/auth.middleware.ts @@ -0,0 +1,42 @@ +import type { MiddlewareHandler } from 'hono'; +import { createMiddleware } from 'hono/factory'; +import { verifyRequestOrigin } from 'lucia'; +import type { HonoTypes } from '../common/types/hono'; +import { container } from 'tsyringe'; +import { LuciaService } from '../services/lucia.service'; + +// resolve dependencies from the container +const { lucia } = container.resolve(LuciaService) + +// Middleware to verify the origin of the request +export const verifyOrigin: MiddlewareHandler = createMiddleware(async (c, next) => { + if (c.req.method === "GET") { + return next(); + } + const originHeader = c.req.header("Origin") ?? null; + const hostHeader = c.req.header("Host") ?? null; + if (!originHeader || !hostHeader || !verifyRequestOrigin(originHeader, [hostHeader])) { + return c.body(null, 403); + } + return next(); +}) + +export const validateAuthSession: MiddlewareHandler = createMiddleware(async (c, next) => { + const sessionId = lucia.readSessionCookie(c.req.header("Cookie") ?? ""); + if (!sessionId) { + c.set("user", null); + c.set("session", null); + return next(); + } + + const { session, user } = await lucia.validateSession(sessionId); + if (session && session.fresh) { + c.header("Set-Cookie", lucia.createSessionCookie(session.id).serialize(), { append: true }); + } + if (!session) { + c.header("Set-Cookie", lucia.createBlankSessionCookie().serialize(), { append: true }); + } + c.set("session", session); + c.set("user", user); + return next(); +}) \ No newline at end of file diff --git a/src/lib/server/api/middlewares/rate-limiter.middlware.ts b/src/lib/server/api/middlewares/rate-limiter.middlware.ts new file mode 100644 index 0000000..79dcb93 --- /dev/null +++ b/src/lib/server/api/middlewares/rate-limiter.middlware.ts @@ -0,0 +1,34 @@ +import { rateLimiter } from "hono-rate-limiter"; +import { RedisStore } from 'rate-limit-redis' +import type { HonoTypes } from "../common/types/hono"; +import { container } from "tsyringe"; +import { RedisService } from '../services/redis.service'; + +// resolve dependencies from the container +const { client } = container.resolve(RedisService); + +// Rate limiter middleware +export function limiter({ limit, minutes, key = "" }: { + limit: number; + minutes: number; + key?: string; +}) { + return rateLimiter({ + windowMs: minutes * 60 * 1000, // every x minutes + limit, // Limit each IP to 100 requests per `window` (here, per 15 minutes). + standardHeaders: "draft-6", // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header + keyGenerator: (c) => { + const vars = c.var as HonoTypes['Variables']; + const clientKey = vars.user?.id || c.req.header("x-forwarded-for"); + const pathKey = key || c.req.routePath; + return `${clientKey}_${pathKey}` + }, // Method to generate custom identifiers for clients. + // Redis store configuration + store: new RedisStore({ + // @ts-expect-error - Known issue: the `call` function is not present in @types/ioredis + sendCommand: (...args: string[]) => client.call(...args), + }) as any + }) +} + + diff --git a/src/lib/server/api/middlewares/require-auth.middleware.ts b/src/lib/server/api/middlewares/require-auth.middleware.ts new file mode 100644 index 0000000..1dfb5b9 --- /dev/null +++ b/src/lib/server/api/middlewares/require-auth.middleware.ts @@ -0,0 +1,15 @@ +import type { MiddlewareHandler } from "hono"; +import { createMiddleware } from "hono/factory"; +import type { Session, User } from "lucia"; +import { Unauthorized } from "../common/exceptions"; + +export const requireAuth: MiddlewareHandler<{ + Variables: { + session: Session; + user: User; + }; +}> = createMiddleware(async (c, next) => { + const user = c.var.user; + if (!user) throw Unauthorized('You must be logged in to access this resource'); + return next(); +}); \ No newline at end of file diff --git a/src/lib/server/api/repositories/email-verifications.repository.ts b/src/lib/server/api/repositories/email-verifications.repository.ts new file mode 100644 index 0000000..c599b9e --- /dev/null +++ b/src/lib/server/api/repositories/email-verifications.repository.ts @@ -0,0 +1,35 @@ +import { inject, injectable } from "tsyringe"; +import { and, eq, gte, type InferInsertModel } from "drizzle-orm"; +import { emailVerificationsTable } from "../databases/postgres/tables"; +import { takeFirst, takeFirstOrThrow } from "../common/utils/repository"; +import { DrizzleService } from "../services/drizzle.service"; + +type Create = Pick, 'requestedEmail' | 'hashedToken' | 'userId' | 'expiresAt'>; + +@injectable() +export class EmailVerificationsRepository { + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) { } + + // creates a new email verification record or updates an existing one + async create(data: Create) { + return this.drizzle.db.insert(emailVerificationsTable).values(data).onConflictDoUpdate({ + target: emailVerificationsTable.userId, + set: data + }).returning().then(takeFirstOrThrow) + } + + // finds a valid record by token and userId + async findValidRecord(userId: string, db = this.drizzle.db) { + return db.select().from(emailVerificationsTable).where( + and( + eq(emailVerificationsTable.userId, userId), + gte(emailVerificationsTable.expiresAt, new Date()) + )).then(takeFirst) + } + + async deleteById(id: string, db = this.drizzle.db) { + return db.delete(emailVerificationsTable).where(eq(emailVerificationsTable.id, id)) + } + + +} \ No newline at end of file diff --git a/src/lib/server/api/repositories/files.repository.ts b/src/lib/server/api/repositories/files.repository.ts new file mode 100644 index 0000000..2208145 --- /dev/null +++ b/src/lib/server/api/repositories/files.repository.ts @@ -0,0 +1,41 @@ +import { inject } from "tsyringe"; +import { StorageService } from "../services/storage.service"; +import { eq } from "drizzle-orm"; +import { filesTable } from "../databases/postgres/tables/files.table"; +import { takeFirst, takeFirstOrThrow } from "../common/utils/repository"; +import { DrizzleService } from "../services/drizzle.service"; + +export class FilesRepository { + constructor( + @inject(StorageService) private readonly storageService: StorageService, + @inject(DrizzleService) private readonly drizzle: DrizzleService) { } + + async create(file: File, db = this.drizzle.db) { + const asset = await this.storageService.upload(file); + return db.insert(filesTable).values({ key: asset.key, contentType: asset.type, size: BigInt(asset.size) }).returning().then(takeFirst) + } + + async findOneById(id: string, db = this.drizzle.db) { + return db.select().from(filesTable).where(eq(filesTable.id, id)).then(takeFirst) + } + + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { + return db.select().from(filesTable).where(eq(filesTable.id, id)).then(takeFirstOrThrow) + } + + async update(id: string, file: File, db = this.drizzle.db) { + // upload new file + const newAsset = await this.storageService.upload(file); + await db.update(filesTable).set({ key: newAsset.key, contentType: newAsset.type, size: BigInt(newAsset.size) }).where(eq(filesTable.id, id)) + + // remove old file + const oldAsset = await this.findOneByIdOrThrow(id) + await this.storageService.delete(oldAsset.key) + } + + async delete(id: string, db = this.drizzle.db) { + const asset = await this.findOneByIdOrThrow(id) + await this.storageService.delete(asset.key) + await db.delete(filesTable).where(eq(filesTable.id, id)) + } +} \ No newline at end of file diff --git a/src/lib/server/api/repositories/login-requests.repository.ts b/src/lib/server/api/repositories/login-requests.repository.ts new file mode 100644 index 0000000..5702474 --- /dev/null +++ b/src/lib/server/api/repositories/login-requests.repository.ts @@ -0,0 +1,34 @@ +import { inject, injectable } from "tsyringe"; +import { and, eq, gte, type InferInsertModel } from "drizzle-orm"; +import { loginRequestsTable } from "../databases/postgres/tables"; +import { takeFirst, takeFirstOrThrow } from "../common/utils/repository"; +import { DrizzleService } from "../services/drizzle.service"; + +type Create = Pick, 'email' | 'expiresAt' | 'hashedToken'>; + +@injectable() +export class LoginRequestsRepository { + constructor( + @inject(DrizzleService) private readonly drizzle: DrizzleService, + ) { } + + async create(data: Create, db = this.drizzle.db) { + return db.insert(loginRequestsTable).values(data).onConflictDoUpdate({ + target: loginRequestsTable.email, + set: data + }).returning().then(takeFirstOrThrow) + } + + async findOneByEmail(email: string, db = this.drizzle.db) { + return db.select().from(loginRequestsTable).where( + and( + eq(loginRequestsTable.email, email), + gte(loginRequestsTable.expiresAt, new Date()) + ) + ).then(takeFirst) + } + + async deleteById(id: string, db = this.drizzle.db) { + return db.delete(loginRequestsTable).where(eq(loginRequestsTable.id, id)); + } +} \ No newline at end of file diff --git a/src/lib/server/api/repositories/users.repository.ts b/src/lib/server/api/repositories/users.repository.ts new file mode 100644 index 0000000..93df2cd --- /dev/null +++ b/src/lib/server/api/repositories/users.repository.ts @@ -0,0 +1,44 @@ +import { inject, injectable } from 'tsyringe'; +import { usersTable } from '../databases/postgres/tables'; +import { eq, type InferInsertModel } from 'drizzle-orm'; +import { takeFirstOrThrow } from '../common/utils/repository'; +import { DrizzleService } from '../services/drizzle.service'; + +export type Create = InferInsertModel; +export type Update = Partial; + +@injectable() +export class UsersRepository { + constructor(@inject(DrizzleService) private drizzle: DrizzleService) { } + + async findOneById(id: string, db = this.drizzle.db) { + return db.query.usersTable.findFirst({ + where: eq(usersTable.id, id) + }); + } + + async findOneByIdOrThrow(id: string, db = this.drizzle.db) { + const user = await this.findOneById(id, db); + if (!user) throw Error('User not found'); + return user; + } + + async findOneByEmail(email: string, db = this.drizzle.db) { + return db.query.usersTable.findFirst({ + where: eq(usersTable.email, email) + }); + } + + async create(data: Create, db = this.drizzle.db) { + return db.insert(usersTable).values(data).returning().then(takeFirstOrThrow); + } + + async update(id: string, data: Update, db = this.drizzle.db) { + return db + .update(usersTable) + .set(data) + .where(eq(usersTable.id, id)) + .returning() + .then(takeFirstOrThrow); + } +} diff --git a/src/lib/server/api/services/authentication.service.ts b/src/lib/server/api/services/authentication.service.ts new file mode 100644 index 0000000..5f09507 --- /dev/null +++ b/src/lib/server/api/services/authentication.service.ts @@ -0,0 +1,80 @@ +import { inject, injectable } from 'tsyringe'; +import { MailerService } from './mailer.service'; +import { TokensService } from './tokens.service'; +import { UsersRepository } from '../repositories/users.repository'; +import type { VerifyLoginDto } from '../dtos/verify-login.dto'; +import type { LoginDto } from '../dtos/login.dto'; +import { LoginRequestsRepository } from '../repositories/login-requests.repository'; +import { LoginVerificationEmail } from '../emails/login-verification.email'; +import { BadRequest } from '../common/exceptions'; +import { WelcomeEmail } from '../emails/welcome.email'; +import { DrizzleService } from './drizzle.service'; +import { LuciaService } from './lucia.service'; + +@injectable() +export class AuthenticationService { + constructor( + @inject(LuciaService) private readonly luciaService: LuciaService, + @inject(DrizzleService) private readonly drizzleService: DrizzleService, + @inject(TokensService) private readonly tokensService: TokensService, + @inject(MailerService) private readonly mailerService: MailerService, + @inject(UsersRepository) private readonly usersRepository: UsersRepository, + @inject(LoginRequestsRepository) private readonly loginRequestsRepository: LoginRequestsRepository, + ) { } + + async createLoginRequest(data: LoginDto) { + // generate a token, expiry date, and hash + const { token, expiry, hashedToken } = await this.tokensService.generateTokenWithExpiryAndHash(15, 'm'); + // save the login request to the database - ensuring we save the hashedToken + await this.loginRequestsRepository.create({ email: data.email, hashedToken, expiresAt: expiry }); + // send the login request email + await this.mailerService.send({ email: new LoginVerificationEmail(token), to: data.email }); + } + + async verifyLoginRequest(data: VerifyLoginDto) { + const validLoginRequest = await this.getValidLoginRequest(data.email, data.token); + if (!validLoginRequest) throw BadRequest('Invalid token'); + + let existingUser = await this.usersRepository.findOneByEmail(data.email); + + if (!existingUser) { + const newUser = await this.handleNewUserRegistration(data.email); + return this.luciaService.lucia.createSession(newUser.id, {}); + } + + return this.luciaService.lucia.createSession(existingUser.id, {}); + } + + async logout(sessionId: string) { + return this.luciaService.lucia.invalidateSession(sessionId); + } + + // Create a new user and send a welcome email - or other onboarding process + private async handleNewUserRegistration(email: string) { + const newUser = await this.usersRepository.create({ email, verified: true }) + await this.mailerService.send({ email: new WelcomeEmail(), to: newUser.email }); + // TODO: add whatever onboarding process or extra data you need here + return newUser + } + + // Fetch a valid request from the database, verify the token and burn the request if it is valid + private async getValidLoginRequest(email: string, token: string) { + return await this.drizzleService.db.transaction(async (trx) => { + // fetch the login request + const loginRequest = await this.loginRequestsRepository.findOneByEmail(email, trx) + if (!loginRequest) return null; + + // check if the token is valid + const isValidRequest = await this.tokensService.verifyHashedToken(loginRequest.hashedToken, token); + if (!isValidRequest) return null + + // if the token is valid, burn the request + await this.loginRequestsRepository.deleteById(loginRequest.id, trx); + return loginRequest + }) + } + + + + +} diff --git a/src/lib/server/api/services/drizzle.service.ts b/src/lib/server/api/services/drizzle.service.ts new file mode 100644 index 0000000..3ee4fa2 --- /dev/null +++ b/src/lib/server/api/services/drizzle.service.ts @@ -0,0 +1,22 @@ +import { drizzle, type PostgresJsDatabase } from "drizzle-orm/postgres-js"; +import postgres from "postgres"; +import { injectable, type Disposable } from "tsyringe"; +import { config } from "../common/config"; +import * as schema from '../databases/postgres/tables'; + +@injectable() +export class DrizzleService implements Disposable { + protected readonly client: postgres.Sql<{}> + readonly db: PostgresJsDatabase + readonly schema: typeof schema = schema; + + constructor() { + const client = postgres(config.postgres.url, { max: 1 }) + this.client = client; + this.db = drizzle(client, { schema }) + } + + dispose(): Promise | void { + this.client.end(); + } +} \ No newline at end of file diff --git a/src/lib/server/api/services/email-verification.service.ts b/src/lib/server/api/services/email-verification.service.ts new file mode 100644 index 0000000..b60d73b --- /dev/null +++ b/src/lib/server/api/services/email-verification.service.ts @@ -0,0 +1,69 @@ +import { inject, injectable } from 'tsyringe'; +import { MailerService } from './mailer.service'; +import { TokensService } from './tokens.service'; +import { UsersRepository } from '../repositories/users.repository'; +import { LoginVerificationEmail } from '../emails/login-verification.email'; +import { BadRequest } from '../common/exceptions'; +import { EmailVerificationsRepository } from '../repositories/email-verifications.repository'; +import { EmailChangeNoticeEmail } from '../emails/email-change-notice.email'; +import { DrizzleService } from './drizzle.service'; + +@injectable() +export class EmailVerificationService { + constructor( + @inject(DrizzleService) private readonly drizzleService: DrizzleService, + @inject(TokensService) private readonly tokensService: TokensService, + @inject(MailerService) private readonly mailerService: MailerService, + @inject(UsersRepository) private readonly usersRepository: UsersRepository, + @inject(EmailVerificationsRepository) private readonly emailVerificationsRepository: EmailVerificationsRepository, + ) { } + + // These steps follow the process outlined in OWASP's "Changing A User's Email Address" guide. + // https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html#changing-a-users-registered-email-address + async create(userId: string, requestedEmail: string) { + // generate a token and expiry + const { token, expiry, hashedToken } = await this.tokensService.generateTokenWithExpiryAndHash(15, 'm') + const user = await this.usersRepository.findOneByIdOrThrow(userId) + + // create a new email verification record + await this.emailVerificationsRepository.create({ requestedEmail, userId, hashedToken, expiresAt: expiry }) + + // A confirmation-required email message to the proposed new address, instructing the user to + // confirm the change and providing a link for unexpected situations + this.mailerService.send({ + to: requestedEmail, + email: new LoginVerificationEmail(token) + }) + + // A notification-only email message to the current address, alerting the user to the impending change and + // providing a link for an unexpected situation. + this.mailerService.send({ + to: user.email, + email: new EmailChangeNoticeEmail() + }) + } + + async verify(userId: string, token: string) { + const validRecord = await this.burnVerificationToken(userId, token) + if (!validRecord) throw BadRequest('Invalid token'); + await this.usersRepository.update(userId, { email: validRecord.requestedEmail, verified: true }); + } + + private async burnVerificationToken(userId: string, token: string) { + return this.drizzleService.db.transaction(async (trx) => { + // find a valid record + const emailVerificationRecord = await this.emailVerificationsRepository.findValidRecord(userId, trx); + if (!emailVerificationRecord) return null; + + // check if the token is valid + const isValidRecord = await this.tokensService.verifyHashedToken(emailVerificationRecord.hashedToken, token); + if (!isValidRecord) return null + + // burn the token if it is valid + await this.emailVerificationsRepository.deleteById(emailVerificationRecord.id, trx) + return emailVerificationRecord + }) + } + + +} diff --git a/src/lib/server/api/services/hashing.service.ts b/src/lib/server/api/services/hashing.service.ts new file mode 100644 index 0000000..432604a --- /dev/null +++ b/src/lib/server/api/services/hashing.service.ts @@ -0,0 +1,45 @@ +import { scrypt } from "node:crypto"; +import { decodeHex, encodeHex } from "oslo/encoding"; +import { constantTimeEqual } from "oslo/crypto"; +import { injectable } from "tsyringe"; + +@injectable() +export class HashingService { + N; + r; + p; + dkLen; + + constructor() { + this.N = 16384; + this.r = 16; + this.p = 1; + this.dkLen = 64; + } + async hash(password: string) { + const salt = encodeHex(crypto.getRandomValues(new Uint8Array(16))); + const key = await this.generateKey(password, salt); + return `${salt}:${encodeHex(key)}`; + } + + async verify(hash: string, password: string) { + const [salt, key] = hash.split(":"); + const targetKey = await this.generateKey(password, salt); + return constantTimeEqual(targetKey, decodeHex(key)); + } + + async generateKey(password: string, salt: string): Promise { + return await new Promise((resolve, reject) => { + scrypt(password.normalize("NFKC"), salt, this.dkLen, { + N: this.N, + p: this.p, + r: this.r, + maxmem: 128 * this.N * this.r * 2 + }, (err, buff) => { + if (err) + return reject(err); + return resolve(buff); + }); + }); + } +} diff --git a/src/lib/server/api/services/iam.service.ts b/src/lib/server/api/services/iam.service.ts new file mode 100644 index 0000000..eb6ea11 --- /dev/null +++ b/src/lib/server/api/services/iam.service.ts @@ -0,0 +1,80 @@ +import { inject, injectable } from 'tsyringe'; +import { MailerService } from './mailer.service'; +import { TokensService } from './tokens.service'; +import { UsersRepository } from '../repositories/users.repository'; +import type { VerifyLoginDto } from '../dtos/verify-login.dto'; +import type { LoginDto } from '../dtos/login.dto'; +import { LoginRequestsRepository } from '../repositories/login-requests.repository'; +import { LoginVerificationEmail } from '../emails/login-verification.email'; +import { BadRequest } from '../common/exceptions'; +import { WelcomeEmail } from '../emails/welcome.email'; +import { DrizzleService } from './drizzle.service'; +import { LuciaService } from './lucia.service'; + +@injectable() +export class IamService { + constructor( + @inject(LuciaService) private readonly luciaService: LuciaService, + @inject(DrizzleService) private readonly drizzleService: DrizzleService, + @inject(TokensService) private readonly tokensService: TokensService, + @inject(MailerService) private readonly mailerService: MailerService, + @inject(UsersRepository) private readonly usersRepository: UsersRepository, + @inject(LoginRequestsRepository) private readonly loginRequestsRepository: LoginRequestsRepository, + ) { } + + async createLoginRequest(data: LoginDto) { + // generate a token, expiry date, and hash + const { token, expiry, hashedToken } = await this.tokensService.generateTokenWithExpiryAndHash(15, 'm'); + // save the login request to the database - ensuring we save the hashedToken + await this.loginRequestsRepository.create({ email: data.email, hashedToken, expiresAt: expiry }); + // send the login request email + await this.mailerService.send({ email: new LoginVerificationEmail(token), to: data.email }); + } + + async verifyLoginRequest(data: VerifyLoginDto) { + const validLoginRequest = await this.getValidLoginRequest(data.email, data.token); + if (!validLoginRequest) throw BadRequest('Invalid token'); + + let existingUser = await this.usersRepository.findOneByEmail(data.email); + + if (!existingUser) { + const newUser = await this.handleNewUserRegistration(data.email); + return this.luciaService.lucia.createSession(newUser.id, {}); + } + + return this.luciaService.lucia.createSession(existingUser.id, {}); + } + + async logout(sessionId: string) { + return this.luciaService.lucia.invalidateSession(sessionId); + } + + // Create a new user and send a welcome email - or other onboarding process + private async handleNewUserRegistration(email: string) { + const newUser = await this.usersRepository.create({ email, verified: true }) + await this.mailerService.send({ email: new WelcomeEmail(), to: newUser.email }); + // TODO: add whatever onboarding process or extra data you need here + return newUser + } + + // Fetch a valid request from the database, verify the token and burn the request if it is valid + private async getValidLoginRequest(email: string, token: string) { + return await this.drizzleService.db.transaction(async (trx) => { + // fetch the login request + const loginRequest = await this.loginRequestsRepository.findOneByEmail(email, trx) + if (!loginRequest) return null; + + // check if the token is valid + const isValidRequest = await this.tokensService.verifyHashedToken(loginRequest.hashedToken, token); + if (!isValidRequest) return null + + // if the token is valid, burn the request + await this.loginRequestsRepository.deleteById(loginRequest.id, trx); + return loginRequest + }) + } + + + + +} diff --git a/src/lib/server/api/services/jobs.service.ts b/src/lib/server/api/services/jobs.service.ts new file mode 100644 index 0000000..5545233 --- /dev/null +++ b/src/lib/server/api/services/jobs.service.ts @@ -0,0 +1,28 @@ +import { injectable } from "tsyringe"; +import { Queue, Worker, type Processor } from 'bullmq'; +import RedisClient from "ioredis"; +import { config } from "../common/config"; + +// BullMQ utilizes ioredis, which is no longer maintained but still works fine. +// I recommend using BullMQ with ioredis for now, but keep an eye out for future updates. + +@injectable() +export class JobsService { + constructor() { } + + createQueue(name: string) { + return new Queue(name, { + connection: new RedisClient(config.redis.url, { + maxRetriesPerRequest: null + }) + }) + } + + createWorker(name: string, prcoessor: Processor) { + return new Worker(name, prcoessor, { + connection: new RedisClient(config.redis.url, { + maxRetriesPerRequest: null + }) + }) + } +} diff --git a/src/lib/server/api/services/lucia.service.ts b/src/lib/server/api/services/lucia.service.ts new file mode 100644 index 0000000..7c6355e --- /dev/null +++ b/src/lib/server/api/services/lucia.service.ts @@ -0,0 +1,25 @@ +import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle"; +import { Lucia } from "lucia"; +import { inject, injectable } from "tsyringe"; +import { DrizzleService } from "./drizzle.service"; +import { config } from "../common/config"; + +@injectable() +export class LuciaService { + readonly lucia: Lucia; + constructor(@inject(DrizzleService) private readonly drizzle: DrizzleService) { + const adapter = new DrizzlePostgreSQLAdapter(this.drizzle.db, this.drizzle.schema.sessionsTable, this.drizzle.schema.usersTable); + this.lucia = new Lucia(adapter, { + sessionCookie: { + attributes: { + secure: config.isProduction + } + }, + getUserAttributes: (attributes) => { + return { + ...attributes + }; + } + }); + } +} \ No newline at end of file diff --git a/src/lib/server/api/services/mailer.service.ts b/src/lib/server/api/services/mailer.service.ts new file mode 100644 index 0000000..209fbb2 --- /dev/null +++ b/src/lib/server/api/services/mailer.service.ts @@ -0,0 +1,43 @@ +import { injectable } from 'tsyringe'; +import { config } from '../common/config'; +import type { Email } from '../common/types/email'; + +type SendProps = { + to: string | string[]; + email: Email; +} + +@injectable() +export class MailerService { + + async send(data: SendProps) { + const mailer = config.isProduction ? this.sendProd : this.sendDev; + await mailer(data); + } + + private async sendDev({ to, email }: SendProps) { + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + Attachments: [], + From: { Email: "noreply@tofustack.com", Name: "TofuStack" }, + HTML: email.html(), + Subject: email.subject(), + Text: email.html(), + To: Array.isArray(to) ? to.map(to => ({ Email: to, Name: to })) : [{ Email: to, Name: to }], + }) + }; + + const response = await fetch('http://localhost:8025/api/v1/send', options) + const data = await response.json() + console.log(`http://localhost:8025/view/${data.ID}`) + } + + private async sendProd({ to, email }: SendProps) { + // CONFIGURE MAILER + } + +} diff --git a/src/lib/server/api/services/redis.service.ts b/src/lib/server/api/services/redis.service.ts new file mode 100644 index 0000000..3fd9eb1 --- /dev/null +++ b/src/lib/server/api/services/redis.service.ts @@ -0,0 +1,16 @@ +import { injectable, type Disposable } from "tsyringe"; +import { config } from "../common/config"; +import { Redis } from "ioredis"; + +@injectable() +export class RedisService implements Disposable { + readonly client: Redis; + + constructor() { + this.client = new Redis(config.redis.url) + } + + async dispose(): Promise { + this.client.disconnect(); + } +} \ No newline at end of file diff --git a/src/lib/server/api/services/storage.service.ts b/src/lib/server/api/services/storage.service.ts new file mode 100644 index 0000000..a15c967 --- /dev/null +++ b/src/lib/server/api/services/storage.service.ts @@ -0,0 +1,44 @@ +import { PutObjectCommand, DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'; +import { createId } from '@paralleldrive/cuid2'; +import { injectable } from 'tsyringe'; +import { config } from '../common/config'; + +@injectable() +export class StorageService { + protected readonly s3Client: S3Client + + constructor() { + this.s3Client = new S3Client({ + region: 'auto', + endpoint: config.storage.url, + credentials: { + accessKeyId: config.storage.accessKey, + secretAccessKey: config.storage.secretKey + }, + forcePathStyle: true + }) + } + + async upload(file: File) { + const key = createId(); + const uploadCommand = new PutObjectCommand({ + Bucket: config.storage.bucket, + ACL: 'public-read', + Key: key, + ContentType: file.type, + Body: new Uint8Array(await file.arrayBuffer()) + }); + + const response = await this.s3Client.send(uploadCommand); + return { ...response, size: file.size, name: file.name, type: file.type, key }; + } + + delete(key: string) { + const deleteCommand = new DeleteObjectCommand({ + Bucket: config.storage.bucket, + Key: key + }); + + return this.s3Client.send(deleteCommand); + } +} diff --git a/src/lib/server/api/services/tokens.service.ts b/src/lib/server/api/services/tokens.service.ts new file mode 100644 index 0000000..6e9cc89 --- /dev/null +++ b/src/lib/server/api/services/tokens.service.ts @@ -0,0 +1,35 @@ +import { inject, injectable } from 'tsyringe'; +import { generateRandomString } from "oslo/crypto"; +import { TimeSpan, createDate, type TimeSpanUnit } from 'oslo'; +import { HashingService } from './hashing.service'; + +@injectable() +export class TokensService { + constructor(@inject(HashingService) private readonly hashingService: HashingService) { } + + generateToken() { + const alphabet = '23456789ACDEFGHJKLMNPQRSTUVWXYZ'; // alphabet with removed look-alike characters (0, 1, O, I) + return generateRandomString(6, alphabet); + } + + generateTokenWithExpiry(number: number, lifespan: TimeSpanUnit) { + return { + token: this.generateToken(), + expiry: createDate(new TimeSpan(number, lifespan)) + } + } + + async generateTokenWithExpiryAndHash(number: number, lifespan: TimeSpanUnit) { + const token = this.generateToken() + const hashedToken = await this.hashingService.hash(token) + return { + token, + hashedToken, + expiry: createDate(new TimeSpan(number, lifespan)) + } + } + + async verifyHashedToken(hashedToken: string, token: string) { + return this.hashingService.verify(hashedToken, token) + } +} diff --git a/src/lib/server/api/tests/login-requests.service.test.ts b/src/lib/server/api/tests/login-requests.service.test.ts new file mode 100644 index 0000000..44e54b6 --- /dev/null +++ b/src/lib/server/api/tests/login-requests.service.test.ts @@ -0,0 +1,71 @@ +import 'reflect-metadata'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; +import { TokensService } from '../services/tokens.service'; +import { MailerService } from '../services/mailer.service'; +import { UsersRepository } from '../repositories/users.repository'; +import { LoginRequestsRepository } from '../repositories/login-requests.repository'; +import { container } from 'tsyringe'; +import { LuciaService } from '../services/lucia.service'; +import { DrizzleService } from '../services/drizzle.service'; +import { IamService } from '../services/iam.service'; + +describe('LoginRequestService', () => { + let service: IamService; + let tokensService = vi.mocked(TokensService.prototype) + let mailerService = vi.mocked(MailerService.prototype); + let usersRepository = vi.mocked(UsersRepository.prototype); + let loginRequestsRepository = vi.mocked(LoginRequestsRepository.prototype); + let luciaService = vi.mocked(LuciaService.prototype); + let drizzleService = vi.mocked(DrizzleService.prototype); + + beforeAll(() => { + service = container + .register(TokensService, { useValue: tokensService }) + .register(MailerService, { useValue: mailerService }) + .register(UsersRepository, { useValue: usersRepository }) + .register(LoginRequestsRepository, { useValue: loginRequestsRepository }) + .register(LuciaService, { useValue: luciaService }) + .register(DrizzleService, { useValue: drizzleService }) + .resolve(IamService); + }); + + afterAll(() => { + vi.resetAllMocks() + }) + + describe('Create', () => { + tokensService.generateTokenWithExpiryAndHash = vi.fn().mockResolvedValue({ + token: "1", + expiry: new Date(), + hashedToken: "xyz" + } satisfies Awaited>) + + loginRequestsRepository.create = vi.fn().mockResolvedValue({ + createdAt: new Date(), + email: 'me@test.com', + expiresAt: new Date(), + hashedToken: '111', + id: '1', + updatedAt: new Date() + } satisfies Awaited>) + + mailerService.send = vi.fn().mockResolvedValue(null) + + const spy_mailerService_sendLoginRequest = vi.spyOn(mailerService, 'send') + const spy_tokensService_generateTokenWithExpiryAndHash = vi.spyOn(tokensService, 'generateTokenWithExpiryAndHash') + const spy_loginRequestsRepository_create = vi.spyOn(loginRequestsRepository, 'create') + + it('should resolve', async () => { + await expect(service.createLoginRequest({ email: "test" })).resolves.toBeUndefined() + }) + it('should generate a token with expiry and hash', async () => { + expect(spy_tokensService_generateTokenWithExpiryAndHash).toBeCalledTimes(1) + }) + it('should send an email with token', async () => { + expect(spy_mailerService_sendLoginRequest).toHaveBeenCalledTimes(1) + }) + it('should create a new login request record', async () => { + expect(spy_loginRequestsRepository_create).toBeCalledTimes(1) + }) + }) +}); diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..d06e983 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,15 @@ +export type SwapDatesWithStrings = { + [k in keyof T]: T[k] extends Date | undefined + ? string + : T[k] extends object + ? SwapDatesWithStrings + : T[k]; +}; + +export type Returned = { + [k in keyof T]: T[k] extends Date | undefined + ? string + : T[k] extends object + ? SwapDatesWithStrings + : T[k]; +}; diff --git a/src/lib/utils/api.ts b/src/lib/utils/api.ts new file mode 100644 index 0000000..79c142b --- /dev/null +++ b/src/lib/utils/api.ts @@ -0,0 +1,25 @@ +import type { ClientResponse } from "hono/client"; + +export async function parseApiResponse(response: ClientResponse) { + if (response.status === 204 || response.headers.get('Content-Length') === '0') { + return response.ok + ? { data: null, error: null, response } + : { data: null, error: 'An unknown error has occured', response }; + } + + if (response.ok) { + const data = await response.json() as T; + + return { data, error: null, status: response.status }; + } + + // handle errors + let error = await response.text(); + try { + error = JSON.parse(error); // attempt to parse as JSON + } catch { + // noop + return { data: null, error, response }; + } + return { data: null, error, response }; +} diff --git a/src/lib/utils/helpers.ts b/src/lib/utils/helpers.ts new file mode 100644 index 0000000..1532472 --- /dev/null +++ b/src/lib/utils/helpers.ts @@ -0,0 +1,21 @@ +import { PUBLIC_IMAGE_URI } from '$env/static/public'; + +export function ciEquals(a: string, b: string) { + return typeof a === 'string' && typeof b === 'string' + ? a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0 + : a === b; +} + +export function getTimezoneAbbr(timezone: string) { + return new Intl.DateTimeFormat('en-US', { + timeZone: timezone, + timeZoneName: 'short' + }) + .format(new Date()) + .split(' ')[1]; +} + +export function getFileByKey(key: string) { + if (key.startsWith('http')) return key; + return `${PUBLIC_IMAGE_URI}/${key}`; +} diff --git a/src/lib/utils/superforms.ts b/src/lib/utils/superforms.ts new file mode 100644 index 0000000..f420765 --- /dev/null +++ b/src/lib/utils/superforms.ts @@ -0,0 +1,20 @@ +import { toast } from "svelte-sonner"; +import { message, type ErrorStatus, type SuperForm, type SuperValidated } from "sveltekit-superforms"; + +export type Message = { + type: 'error' | 'success', + text: string +} + +export function errorMessage(form: SuperValidated, text: string | null, status: ErrorStatus = 500) { + return message(form, {text: text || "Error", type: 'error'}, {status}) +} + +export function successMessage(form: SuperValidated, text: string | null) { + return message(form, {text: text || "Success", type: 'success'}) +} + +export function toastMessage(message: Message| undefined) { + if (!message) return + toast[message.type](message.text) +} \ No newline at end of file diff --git a/src/lib/utils/ui.ts b/src/lib/utils/ui.ts new file mode 100644 index 0000000..8871245 --- /dev/null +++ b/src/lib/utils/ui.ts @@ -0,0 +1,62 @@ +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import { cubicOut } from "svelte/easing"; +import type { TransitionConfig } from "svelte/transition"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +type FlyAndScaleParams = { + y?: number; + x?: number; + start?: number; + duration?: number; +}; + +export const flyAndScale = ( + node: Element, + params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 } +): TransitionConfig => { + const style = getComputedStyle(node); + const transform = style.transform === "none" ? "" : style.transform; + + const scaleConversion = ( + valueA: number, + scaleA: [number, number], + scaleB: [number, number] + ) => { + const [minA, maxA] = scaleA; + const [minB, maxB] = scaleB; + + const percentage = (valueA - minA) / (maxA - minA); + const valueB = percentage * (maxB - minB) + minB; + + return valueB; + }; + + const styleToString = ( + style: Record + ): string => { + return Object.keys(style).reduce((str, key) => { + if (style[key] === undefined) return str; + return str + `${key}:${style[key]};`; + }, ""); + }; + + return { + duration: params.duration ?? 200, + delay: 0, + css: (t) => { + const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]); + const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]); + const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]); + + return styleToString({ + transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`, + opacity: t + }); + }, + easing: cubicOut + }; +}; \ No newline at end of file diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte new file mode 100644 index 0000000..7717e7b --- /dev/null +++ b/src/routes/(app)/+layout.svelte @@ -0,0 +1,121 @@ + + +
    +
    + + + + + + + + + +
    +
    +
    + + +
    +
    + {#if data.authedUser} + {@render userDropdown()} + {:else} + + {/if} +
    +
    +
    + {@render children()} +
    +
    + +{#snippet userDropdown()} + + + + + + Settings + + +
    + +
    +
    +
    +{/snippet} diff --git a/src/routes/(app)/+page.server.ts b/src/routes/(app)/+page.server.ts new file mode 100644 index 0000000..b0477fd --- /dev/null +++ b/src/routes/(app)/+page.server.ts @@ -0,0 +1,15 @@ +import { StatusCodes } from "$lib/constants/status-codes"; +import { redirect } from "@sveltejs/kit"; + +export const load = async ({ locals }) => { + const user = await locals.getAuthedUser(); + return { user: user }; +}; + +export const actions = { + logout: async ({ locals }) => { + await locals.api.iam.logout.$post() + redirect(StatusCodes.SEE_OTHER, '/register') + } +} + diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte new file mode 100644 index 0000000..47868e3 --- /dev/null +++ b/src/routes/(app)/+page.svelte @@ -0,0 +1,6 @@ + + +

    Welcome {data?.user?.email}

    +

    Visit kit.svelte.dev to read the documentation

    diff --git a/src/routes/(app)/settings/+layout.svelte b/src/routes/(app)/settings/+layout.svelte new file mode 100644 index 0000000..2a8e36d --- /dev/null +++ b/src/routes/(app)/settings/+layout.svelte @@ -0,0 +1,31 @@ + + +
    +

    Settings

    +
    +
    + +
    + {@render children()} +
    +
    diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/(app)/settings/account/+page.server.ts b/src/routes/(app)/settings/account/+page.server.ts new file mode 100644 index 0000000..a8cc726 --- /dev/null +++ b/src/routes/(app)/settings/account/+page.server.ts @@ -0,0 +1,32 @@ +import { zod } from "sveltekit-superforms/adapters"; +import { fail, setError, superValidate } from "sveltekit-superforms"; +import { StatusCodes } from "$lib/constants/status-codes.js"; +import { updateEmailFormSchema, verifyEmailFormSchema } from "./schemas.js"; + +export let load = async (event) => { + const authedUser = await event.locals.getAuthedUserOrThrow() + + return { + authedUser, + updateEmailForm: await superValidate(authedUser, zod(updateEmailFormSchema)), + verifyEmailForm: await superValidate(zod(verifyEmailFormSchema)) + }; +}; + +export const actions = { + updateEmail: async ({ request, locals }) => { + const updateEmailForm = await superValidate(request, zod(updateEmailFormSchema)); + if (!updateEmailForm.valid) return fail(StatusCodes.BAD_REQUEST, { updateEmailForm }) + const { error } = await locals.api.iam.email.$patch({ json: updateEmailForm.data }).then(locals.parseApiResponse); + if (error) return setError(updateEmailForm, 'email', error); + return { updateEmailForm } + }, + verifyEmail: async ({ request, locals }) => { + const verifyEmailForm = await superValidate(request, zod(verifyEmailFormSchema)); + console.log(verifyEmailForm) + if (!verifyEmailForm.valid) return fail(StatusCodes.BAD_REQUEST, { verifyEmailForm }) + const { error } = await locals.api.iam.email.verify.$post({ json: verifyEmailForm.data }).then(locals.parseApiResponse); + if (error) return setError(verifyEmailForm, 'token', error); + return { verifyEmailForm } + } +}; diff --git a/src/routes/(app)/settings/account/+page.svelte b/src/routes/(app)/settings/account/+page.svelte new file mode 100644 index 0000000..f1745ad --- /dev/null +++ b/src/routes/(app)/settings/account/+page.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/routes/(app)/settings/account/schemas.ts b/src/routes/(app)/settings/account/schemas.ts new file mode 100644 index 0000000..793dabd --- /dev/null +++ b/src/routes/(app)/settings/account/schemas.ts @@ -0,0 +1,9 @@ +import { z } from "zod"; + +export const verifyEmailFormSchema = z.object({ + token: z.string() +}); + +export const updateEmailFormSchema = z.object({ + email: z.string().email() +}); \ No newline at end of file diff --git a/src/routes/(app)/settings/account/update-email-card.svelte b/src/routes/(app)/settings/account/update-email-card.svelte new file mode 100644 index 0000000..2b4c44a --- /dev/null +++ b/src/routes/(app)/settings/account/update-email-card.svelte @@ -0,0 +1,100 @@ + + + + + + + Change Email + Used to identify your store in the marketplace. + + +
    + + + Email + + + + + +
    +
    + + submitEmailForm()}>Submit + +
    + + + + + + Verify Email + + A code has been sent to the email address specified. Enter the code to confirm your address + change. + + +
    + + + + + + + +
    + + verifyEmailFormSubmit()}>Verify + +
    +
    diff --git a/src/routes/(auth)/register/+page.server.ts b/src/routes/(auth)/register/+page.server.ts new file mode 100644 index 0000000..a0612a8 --- /dev/null +++ b/src/routes/(auth)/register/+page.server.ts @@ -0,0 +1,29 @@ +import { fail, redirect } from '@sveltejs/kit'; +import { zod } from 'sveltekit-superforms/adapters'; +import { StatusCodes } from '$lib/constants/status-codes'; +import { setError, superValidate } from 'sveltekit-superforms'; +import { registerFormSchema, signInFormSchema } from './schemas'; + +export const load = async () => { + return { + emailRegisterForm: await superValidate(zod(registerFormSchema)), + emailSigninForm: await superValidate({email: 'test'}, zod(signInFormSchema)) + }; +}; + +export const actions = { + register: async ({ locals, request }) => { + const emailRegisterForm = await superValidate(request, zod(registerFormSchema)); + if (!emailRegisterForm.valid) return fail(StatusCodes.BAD_REQUEST, { emailRegisterForm }); + const { error } = await locals.api.iam.login.$post({ json: emailRegisterForm.data }).then(locals.parseApiResponse); + if (error) return setError(emailRegisterForm, 'email', error); + return { emailRegisterForm }; + }, + signin: async ({ locals, request }) => { + const emailSignInForm = await superValidate(request, zod(signInFormSchema)); + if (!emailSignInForm.valid) return fail(StatusCodes.BAD_REQUEST, { emailSignInForm }); + const { error } = await locals.api.iam.login.verify.$post({ json: emailSignInForm.data }).then(locals.parseApiResponse) + if (error) return setError(emailSignInForm, 'token', error); + redirect(301, '/'); + } +}; diff --git a/src/routes/(auth)/register/+page.svelte b/src/routes/(auth)/register/+page.svelte new file mode 100644 index 0000000..b001a88 --- /dev/null +++ b/src/routes/(auth)/register/+page.svelte @@ -0,0 +1,87 @@ + + + + + Login + Enter your email below to login to your account + + +
    + {#if showTokenVerification} + {@render tokenForm()} + {:else} + {@render emailForm()} + {/if} + +
    +
    + By registering, you agree to our Terms of Service +
    +
    +
    + +{#snippet emailForm()} +
    + + + Email + + + + + + +
    +{/snippet} + +{#snippet tokenForm()} +
    + + + + + + + + + + +
    +{/snippet} diff --git a/src/routes/(auth)/register/schemas.ts b/src/routes/(auth)/register/schemas.ts new file mode 100644 index 0000000..65cf444 --- /dev/null +++ b/src/routes/(auth)/register/schemas.ts @@ -0,0 +1,12 @@ +import { z } from "zod"; + +export const registerFormSchema = z.object({ + email: z.string().email() +}); + +export const signInFormSchema = z.object({ + email: z.string().email(), + token: z.string() +}); + + diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts new file mode 100644 index 0000000..fcf4c2b --- /dev/null +++ b/src/routes/+layout.server.ts @@ -0,0 +1,6 @@ +export const load = async ({ locals }) => { + const authedUser = await locals.getAuthedUser(); + return { + authedUser + } +} \ No newline at end of file diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..582b1c7 --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,11 @@ + + + + +{@render children()} diff --git a/src/routes/api/[...slug]/+server.ts b/src/routes/api/[...slug]/+server.ts new file mode 100644 index 0000000..5b4a8e3 --- /dev/null +++ b/src/routes/api/[...slug]/+server.ts @@ -0,0 +1,9 @@ +import { app } from '$lib/server/api'; +import type { RequestHandler } from '@sveltejs/kit'; + +export const GET: RequestHandler = ({ request }) => app.request(request); +export const PUT: RequestHandler = ({ request }) => app.request(request); +export const DELETE: RequestHandler = ({ request }) => app.fetch(request); +export const POST: RequestHandler = ({ request }) => app.fetch(request); +export const PATCH: RequestHandler = ({ request }) => app.fetch(request); +export const fallback: RequestHandler = ({ request }) => app.fetch(request); diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH)", + input: "hsl(var(--input) / )", + ring: "hsl(var(--ring) / )", + background: "hsl(var(--background) / )", + foreground: "hsl(var(--foreground) / )", + primary: { + DEFAULT: "hsl(var(--primary) / )", + foreground: "hsl(var(--primary-foreground) / )" + }, + secondary: { + DEFAULT: "hsl(var(--secondary) / )", + foreground: "hsl(var(--secondary-foreground) / )" + }, + destructive: { + DEFAULT: "hsl(var(--destructive) / )", + foreground: "hsl(var(--destructive-foreground) / )" + }, + muted: { + DEFAULT: "hsl(var(--muted) / )", + foreground: "hsl(var(--muted-foreground) / )" + }, + accent: { + DEFAULT: "hsl(var(--accent) / )", + foreground: "hsl(var(--accent-foreground) / )" + }, + popover: { + DEFAULT: "hsl(var(--popover) / )", + foreground: "hsl(var(--popover-foreground) / )" + }, + card: { + DEFAULT: "hsl(var(--card) / )", + foreground: "hsl(var(--card-foreground) / )" + } + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)" + }, + fontFamily: { + sans: [...fontFamily.sans] + } + } + }, +}; + +export default config; diff --git a/tests/test.ts b/tests/test.ts new file mode 100644 index 0000000..5816be4 --- /dev/null +++ b/tests/test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('index page has expected h1', async ({ page }) => { + await page.goto('/'); + await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible(); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e0f8251 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler", + "experimentalDecorators": true, + "emitDecoratorMetadata": true + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias + // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..37b6a84 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,9 @@ +import { sveltekit } from '@sveltejs/kit/vite'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: [sveltekit()], + test: { + include: ['src/**/*.{test,spec}.{js,ts}'] + } +}); diff --git a/volume/cache/machine.json b/volume/cache/machine.json new file mode 100644 index 0000000..61dbe34 --- /dev/null +++ b/volume/cache/machine.json @@ -0,0 +1 @@ +{"machine_id": "dkr_4e8cc7cb0ecc"} \ No newline at end of file diff --git a/volume/cache/server.test.pem b/volume/cache/server.test.pem new file mode 100644 index 0000000..0fa0ac2 --- /dev/null +++ b/volume/cache/server.test.pem @@ -0,0 +1,119 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmuU6GRc/KMXzc ++qVGR0hrMaFze3C9nG24mEeRdGOdpOqDnFoC1OANAY5nOCPLJzPB3lS+bYZj+6RU +oPoDSL1Kd5TS8bZEIBgvbkAHexEwQwbtOnPS6j2lL9o0BrLh5OKEv07DinpaPx1H +EQatZ59+qZnbIEo81fAA0jJUcfVNamb7LBj5sMnpvMS/JnLWmSyOD1/aKUqvixNe +lNMHZvHWPymN1I/qJa85hNPMVO/4fioyC79DhtUuPl5eLC6RxDU7dv4SBLhNPMYV +wdM0k1ymUzGDihJ5lpISavX6b/4+inpHzVstGBAXE9xM2hh+hzvlpdULs+KZo8em +gIIAOiDtAgMBAAECggEASC1pBVAryMjr2W7ZJjet7loqHyiNgki6Z3PlZ98PUSwY +KqoBfcBSzs6hq6XuOQDbs05hOZ+I0rgaSFj4Y3uWFyr1zuy9j3ilf8MnDRYGNvKN +iR4JDoJB9cVlnahYwNqqBfYcTyMgHPm93wpL7b4ymk8qQGcWPIgRwwk8qLo9DCoV +SKEcLPUByv/oRB3VuzTXq9qKK7Qznn6AU5U2ulF+gerG00eYreDkYrAC2xpLYrGY +d3nORW8jA0jfr8m1rvX8p5dKnLmkM1ZMWSUJQg76Vz6iY7S8A0Z1TRFiYDifqdEb +CK0eo6FuVKf5D1tgwFZP31gX06kI8E0bjhsCg2GDsQKBgQDS2cuHo6AxgBPDmxyy +pjpnpvE0y6KNzReg++ZSL0ra6OZYCxHoPXF7zLxYqQt4P1TCTJE+6OxGZhw0lLEN +U3FEe2X0gUK6/YF/iaCQNiWB97U3CV1OW4VOTawh1xKZYjuin4HbdO7irRkSAym4 +6tsOTYJbB2i8ahyjSvm53hbutwKBgQDKbJt2ZJllIEUbz/9EdNl0qgfF3u+ODI0V +LWVldGLABen5MX7f7bo1Mn24gInC0lhVOipvCWJbzFI1+uoQKnn1koTfX7ThOR2O +hQsdnF2AQHSsrZPiHBifTUsDw9ap9F/VgwvyfCOseYzybZiyMZ6IkSxTngBTQJ30 +Etmt6LcJewKBgE7nXAf1ToRXpo3DpRihpieVzJvyPHGON3Jx8b39nqiPEWwPMHNV +Uvt+IVmYYQdtw702RABjz8+EdLekkSEogbGb8ApwuNUa+vQMP77X1G9vkCv5YCZr +j1Y/MNQ1FOu7XA++Wy0R9Dd1iXU5I8rkcHdIwChqfGJN30uoSg2pM7G/AoGBAKDJ +3j8Pr4zVMi/iaticnHJ/8Maqy8wgihxNP+JzrVDsIarQNwB2W9ePsK9SYpr+7C1e +k4A5iwhx5sd79Fo88z0uUh8AbbQM4z5mzaqKnvaVvFfBVNthB+nZwoFOGQBM3abC +fkXxd4Cz2FJk3cqFgXDnJ7ePpKB8jjrmkkQCuwlrAoGBAKOB3CY7DyMzzWdUY/pk ++Zh8/JquFmm3F6MeRhsdifc2IeigwU+FTQTmQSTWtfInAsZ0jOgkihYgqRi8+W2y +r7nYQTlW2zfoMKkqZQ6xiRiBy2PaYwmdkSCSZAQIQ41rBjBlsL95MHcib/xjGBim +736norwdHWD3IrjS1fJWJglu +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIILCzCCCfOgAwIBAgISAx0saYDSPGV3sv//Ssy38WrAMA0GCSqGSIb3DQEBCwUA +MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD +EwJSMzAeFw0yNDA2MDEwNTA4NTNaFw0yNDA4MzAwNTA4NTJaMCUxIzAhBgNVBAMT +GmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAprlOhkXPyjF83PqlRkdIazGhc3twvZxtuJhHkXRjnaTqg5xa +AtTgDQGOZzgjyyczwd5Uvm2GY/ukVKD6A0i9SneU0vG2RCAYL25AB3sRMEMG7Tpz +0uo9pS/aNAay4eTihL9Ow4p6Wj8dRxEGrWeffqmZ2yBKPNXwANIyVHH1TWpm+ywY ++bDJ6bzEvyZy1pksjg9f2ilKr4sTXpTTB2bx1j8pjdSP6iWvOYTTzFTv+H4qMgu/ +Q4bVLj5eXiwukcQ1O3b+EgS4TTzGFcHTNJNcplMxg4oSeZaSEmr1+m/+Pop6R81b +LRgQFxPcTNoYfoc75aXVC7PimaPHpoCCADog7QIDAQABo4IIJjCCCCIwDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB +Af8EAjAAMB0GA1UdDgQWBBQn7Yd00V9tcEmukJkQCDK8+QA6UjAfBgNVHSMEGDAW +gBQULrMXt1hWy65QCUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUH +MAGGFWh0dHA6Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3Iz +LmkubGVuY3Iub3JnLzCCBi4GA1UdEQSCBiUwggYhgicqLmFtcGxpZnlhcHAubG9j +YWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCJyouY2xvdWRmcm9udC5sb2NhbGhvc3Qu +bG9jYWxzdGFjay5jbG91ZIIxKi5ka3IuZWNyLmV1LWNlbnRyYWwtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLmV1LXdlc3QtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLWVhc3QtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLWVhc3QtMi5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLXdlc3QtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLXdlc3QtMi5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIgKi5lbGIubG9jYWxob3N0LmxvY2Fsc3RhY2su +Y2xvdWSCNCouZXUtY2VudHJhbC0xLm9wZW5zZWFyY2gubG9jYWxob3N0LmxvY2Fs +c3RhY2suY2xvdWSCMSouZXUtd2VzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0Lmxv +Y2Fsc3RhY2suY2xvdWSCKCouZXhlY3V0ZS1hcGkubG9jYWxob3N0LmxvY2Fsc3Rh +Y2suY2xvdWSCNCoubGFtYmRhLXVybC5ldS1jZW50cmFsLTEubG9jYWxob3N0Lmxv +Y2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC5ldS13ZXN0LTEubG9jYWxob3N0 +LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy1lYXN0LTEubG9jYWxo +b3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy1lYXN0LTIubG9j +YWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy13ZXN0LTEu +bG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy13ZXN0 +LTIubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCHCoubG9jYWxob3N0LmxvY2Fs +c3RhY2suY2xvdWSCJyoub3BlbnNlYXJjaC5sb2NhbGhvc3QubG9jYWxzdGFjay5j +bG91ZIInKi5zMy13ZWJzaXRlLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vkgh8q +LnMzLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgiAqLnNjbS5sb2NhbGhvc3Qu +bG9jYWxzdGFjay5jbG91ZIImKi5zbm93Zmxha2UubG9jYWxob3N0LmxvY2Fsc3Rh +Y2suY2xvdWSCMSoudXMtZWFzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0LmxvY2Fs +c3RhY2suY2xvdWSCMSoudXMtZWFzdC0yLm9wZW5zZWFyY2gubG9jYWxob3N0Lmxv +Y2Fsc3RhY2suY2xvdWSCMSoudXMtd2VzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0 +LmxvY2Fsc3RhY2suY2xvdWSCMSoudXMtd2VzdC0yLm9wZW5zZWFyY2gubG9jYWxo +b3N0LmxvY2Fsc3RhY2suY2xvdWSCGmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vk +gitzcXMuZXUtY2VudHJhbC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vkgihz +cXMuZXUtd2VzdC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMt +ZWFzdC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtZWFzdC0y +LmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtd2VzdC0xLmxvY2Fs +aG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtd2VzdC0yLmxvY2FsaG9zdC5s +b2NhbHN0YWNrLmNsb3VkMBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBAwYKKwYBBAHW +eQIEAgSB9ASB8QDvAHUAPxdLT9ciR1iUHWUchL4NEu2QN38fhWrrwb8ohez4ZG4A +AAGP0mpOGwAABAMARjBEAiB5sV2rP0U9GU19xHb2u0rKJ1tg/39OB42jaruRQmEX +MgIgAoudClE+rY4Jx38b2kVBjYDKmyy+3rnJgo0p+Qq/cMIAdgAZmBBxCfDWUi4w +gNKeP2S7g24ozPkPUo7u385KPxa0ygAAAY/Sak4qAAAEAwBHMEUCIQDtY4+c4S42 +J6LXeDWMLSOyctL4c/CrBylwwkj34y9x3AIgbeSmmtYRFa0X2aGRnuiFWW26bp8t +8z+LUIal4LXRCK0wDQYJKoZIhvcNAQELBQADggEBAIROD+OEV8sV8IHCqPE97BhL +dcreAdYbHfBHr/fuHxhBxL01I7ocfH4fWk9+mXmbTmqaO95R63bQY5I1E6riUXdQ +kbDN1tM21d41GbgN/Y4ihHeeBTx3Xwch5j/3MEjHAHCo4rP8iizT/X/4kttuSEXC +LM8zav2rbR1izWq35Z0m571axpU8gJcCzQHFU/Z8E2tSVZ+WelFogIpe7LHu7UIo +o70j9UQ0AVEqrCos97x2O5mIeuYuJW0SlXFd4R20U52+L/P5XU/h2NGZPTx70VTT +S36fAzFVc+vbpnRt6Klu0sxf42zq1uVIi7b6UQP0UiGZvdjhioxfoJh+yIJI0XI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- diff --git a/volume/cache/server.test.pem.crt b/volume/cache/server.test.pem.crt new file mode 100644 index 0000000..389365b --- /dev/null +++ b/volume/cache/server.test.pem.crt @@ -0,0 +1,91 @@ +-----BEGIN CERTIFICATE----- +MIILCzCCCfOgAwIBAgISAx0saYDSPGV3sv//Ssy38WrAMA0GCSqGSIb3DQEBCwUA +MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD +EwJSMzAeFw0yNDA2MDEwNTA4NTNaFw0yNDA4MzAwNTA4NTJaMCUxIzAhBgNVBAMT +GmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAprlOhkXPyjF83PqlRkdIazGhc3twvZxtuJhHkXRjnaTqg5xa +AtTgDQGOZzgjyyczwd5Uvm2GY/ukVKD6A0i9SneU0vG2RCAYL25AB3sRMEMG7Tpz +0uo9pS/aNAay4eTihL9Ow4p6Wj8dRxEGrWeffqmZ2yBKPNXwANIyVHH1TWpm+ywY ++bDJ6bzEvyZy1pksjg9f2ilKr4sTXpTTB2bx1j8pjdSP6iWvOYTTzFTv+H4qMgu/ +Q4bVLj5eXiwukcQ1O3b+EgS4TTzGFcHTNJNcplMxg4oSeZaSEmr1+m/+Pop6R81b +LRgQFxPcTNoYfoc75aXVC7PimaPHpoCCADog7QIDAQABo4IIJjCCCCIwDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB +Af8EAjAAMB0GA1UdDgQWBBQn7Yd00V9tcEmukJkQCDK8+QA6UjAfBgNVHSMEGDAW +gBQULrMXt1hWy65QCUDmH6+dixTCxjBVBggrBgEFBQcBAQRJMEcwIQYIKwYBBQUH +MAGGFWh0dHA6Ly9yMy5vLmxlbmNyLm9yZzAiBggrBgEFBQcwAoYWaHR0cDovL3Iz +LmkubGVuY3Iub3JnLzCCBi4GA1UdEQSCBiUwggYhgicqLmFtcGxpZnlhcHAubG9j +YWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCJyouY2xvdWRmcm9udC5sb2NhbGhvc3Qu +bG9jYWxzdGFjay5jbG91ZIIxKi5ka3IuZWNyLmV1LWNlbnRyYWwtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLmV1LXdlc3QtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLWVhc3QtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLWVhc3QtMi5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLXdlc3QtMS5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLXdlc3QtMi5sb2NhbGhv +c3QubG9jYWxzdGFjay5jbG91ZIIgKi5lbGIubG9jYWxob3N0LmxvY2Fsc3RhY2su +Y2xvdWSCNCouZXUtY2VudHJhbC0xLm9wZW5zZWFyY2gubG9jYWxob3N0LmxvY2Fs +c3RhY2suY2xvdWSCMSouZXUtd2VzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0Lmxv +Y2Fsc3RhY2suY2xvdWSCKCouZXhlY3V0ZS1hcGkubG9jYWxob3N0LmxvY2Fsc3Rh +Y2suY2xvdWSCNCoubGFtYmRhLXVybC5ldS1jZW50cmFsLTEubG9jYWxob3N0Lmxv +Y2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC5ldS13ZXN0LTEubG9jYWxob3N0 +LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy1lYXN0LTEubG9jYWxo +b3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy1lYXN0LTIubG9j +YWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy13ZXN0LTEu +bG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy13ZXN0 +LTIubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCHCoubG9jYWxob3N0LmxvY2Fs +c3RhY2suY2xvdWSCJyoub3BlbnNlYXJjaC5sb2NhbGhvc3QubG9jYWxzdGFjay5j +bG91ZIInKi5zMy13ZWJzaXRlLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vkgh8q +LnMzLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgiAqLnNjbS5sb2NhbGhvc3Qu +bG9jYWxzdGFjay5jbG91ZIImKi5zbm93Zmxha2UubG9jYWxob3N0LmxvY2Fsc3Rh +Y2suY2xvdWSCMSoudXMtZWFzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0LmxvY2Fs +c3RhY2suY2xvdWSCMSoudXMtZWFzdC0yLm9wZW5zZWFyY2gubG9jYWxob3N0Lmxv +Y2Fsc3RhY2suY2xvdWSCMSoudXMtd2VzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0 +LmxvY2Fsc3RhY2suY2xvdWSCMSoudXMtd2VzdC0yLm9wZW5zZWFyY2gubG9jYWxo +b3N0LmxvY2Fsc3RhY2suY2xvdWSCGmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vk +gitzcXMuZXUtY2VudHJhbC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vkgihz +cXMuZXUtd2VzdC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMt +ZWFzdC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtZWFzdC0y +LmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtd2VzdC0xLmxvY2Fs +aG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtd2VzdC0yLmxvY2FsaG9zdC5s +b2NhbHN0YWNrLmNsb3VkMBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBAwYKKwYBBAHW +eQIEAgSB9ASB8QDvAHUAPxdLT9ciR1iUHWUchL4NEu2QN38fhWrrwb8ohez4ZG4A +AAGP0mpOGwAABAMARjBEAiB5sV2rP0U9GU19xHb2u0rKJ1tg/39OB42jaruRQmEX +MgIgAoudClE+rY4Jx38b2kVBjYDKmyy+3rnJgo0p+Qq/cMIAdgAZmBBxCfDWUi4w +gNKeP2S7g24ozPkPUo7u385KPxa0ygAAAY/Sak4qAAAEAwBHMEUCIQDtY4+c4S42 +J6LXeDWMLSOyctL4c/CrBylwwkj34y9x3AIgbeSmmtYRFa0X2aGRnuiFWW26bp8t +8z+LUIal4LXRCK0wDQYJKoZIhvcNAQELBQADggEBAIROD+OEV8sV8IHCqPE97BhL +dcreAdYbHfBHr/fuHxhBxL01I7ocfH4fWk9+mXmbTmqaO95R63bQY5I1E6riUXdQ +kbDN1tM21d41GbgN/Y4ihHeeBTx3Xwch5j/3MEjHAHCo4rP8iizT/X/4kttuSEXC +LM8zav2rbR1izWq35Z0m571axpU8gJcCzQHFU/Z8E2tSVZ+WelFogIpe7LHu7UIo +o70j9UQ0AVEqrCos97x2O5mIeuYuJW0SlXFd4R20U52+L/P5XU/h2NGZPTx70VTT +S36fAzFVc+vbpnRt6Klu0sxf42zq1uVIi7b6UQP0UiGZvdjhioxfoJh+yIJI0XI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/volume/cache/server.test.pem.key b/volume/cache/server.test.pem.key new file mode 100644 index 0000000..4638574 --- /dev/null +++ b/volume/cache/server.test.pem.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmuU6GRc/KMXzc ++qVGR0hrMaFze3C9nG24mEeRdGOdpOqDnFoC1OANAY5nOCPLJzPB3lS+bYZj+6RU +oPoDSL1Kd5TS8bZEIBgvbkAHexEwQwbtOnPS6j2lL9o0BrLh5OKEv07DinpaPx1H +EQatZ59+qZnbIEo81fAA0jJUcfVNamb7LBj5sMnpvMS/JnLWmSyOD1/aKUqvixNe +lNMHZvHWPymN1I/qJa85hNPMVO/4fioyC79DhtUuPl5eLC6RxDU7dv4SBLhNPMYV +wdM0k1ymUzGDihJ5lpISavX6b/4+inpHzVstGBAXE9xM2hh+hzvlpdULs+KZo8em +gIIAOiDtAgMBAAECggEASC1pBVAryMjr2W7ZJjet7loqHyiNgki6Z3PlZ98PUSwY +KqoBfcBSzs6hq6XuOQDbs05hOZ+I0rgaSFj4Y3uWFyr1zuy9j3ilf8MnDRYGNvKN +iR4JDoJB9cVlnahYwNqqBfYcTyMgHPm93wpL7b4ymk8qQGcWPIgRwwk8qLo9DCoV +SKEcLPUByv/oRB3VuzTXq9qKK7Qznn6AU5U2ulF+gerG00eYreDkYrAC2xpLYrGY +d3nORW8jA0jfr8m1rvX8p5dKnLmkM1ZMWSUJQg76Vz6iY7S8A0Z1TRFiYDifqdEb +CK0eo6FuVKf5D1tgwFZP31gX06kI8E0bjhsCg2GDsQKBgQDS2cuHo6AxgBPDmxyy +pjpnpvE0y6KNzReg++ZSL0ra6OZYCxHoPXF7zLxYqQt4P1TCTJE+6OxGZhw0lLEN +U3FEe2X0gUK6/YF/iaCQNiWB97U3CV1OW4VOTawh1xKZYjuin4HbdO7irRkSAym4 +6tsOTYJbB2i8ahyjSvm53hbutwKBgQDKbJt2ZJllIEUbz/9EdNl0qgfF3u+ODI0V +LWVldGLABen5MX7f7bo1Mn24gInC0lhVOipvCWJbzFI1+uoQKnn1koTfX7ThOR2O +hQsdnF2AQHSsrZPiHBifTUsDw9ap9F/VgwvyfCOseYzybZiyMZ6IkSxTngBTQJ30 +Etmt6LcJewKBgE7nXAf1ToRXpo3DpRihpieVzJvyPHGON3Jx8b39nqiPEWwPMHNV +Uvt+IVmYYQdtw702RABjz8+EdLekkSEogbGb8ApwuNUa+vQMP77X1G9vkCv5YCZr +j1Y/MNQ1FOu7XA++Wy0R9Dd1iXU5I8rkcHdIwChqfGJN30uoSg2pM7G/AoGBAKDJ +3j8Pr4zVMi/iaticnHJ/8Maqy8wgihxNP+JzrVDsIarQNwB2W9ePsK9SYpr+7C1e +k4A5iwhx5sd79Fo88z0uUh8AbbQM4z5mzaqKnvaVvFfBVNthB+nZwoFOGQBM3abC +fkXxd4Cz2FJk3cqFgXDnJ7ePpKB8jjrmkkQCuwlrAoGBAKOB3CY7DyMzzWdUY/pk ++Zh8/JquFmm3F6MeRhsdifc2IeigwU+FTQTmQSTWtfInAsZ0jOgkihYgqRi8+W2y +r7nYQTlW2zfoMKkqZQ6xiRiBy2PaYwmdkSCSZAQIQ41rBjBlsL95MHcib/xjGBim +736norwdHWD3IrjS1fJWJglu +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/volume/cache/service-catalog-3_4_1_dev-1_34_122.pickle b/volume/cache/service-catalog-3_4_1_dev-1_34_122.pickle new file mode 100644 index 0000000000000000000000000000000000000000..a4b65116bb6ab4dcfb018804377bab0a263fb33f GIT binary patch literal 4705 zcmb7IOK%%D5Dxl49N9`0J#4^eU^geXMSVzqfvgmb0lQHx+c^aWwHiyTSIZ5T>sW^X z&84Tkb^CuiT&}syh+4Ti>ig!wd6N6rH~(I?9~Hl>6N-R^iDJRcA^VsdCNTtg))|4k zvSwn?tBB1Z$=~B&UnQ^d?Ca!1l0()}Oin>v#S*Uh z-4!o{Kjm3F;nRpm(?ZPtZDil)vq#x>Y4uc0AUvKxr1&)liH2v7vkeJ}`sHpO=6~m( zb7qX8SZlVCefuE=xiCPQwL}b(DK4VKvC{32g;b|$sCdkzx`;!;Cg?jVcszS%bnXnq zJPtuYJ*_bi@#5|HPY4uIur-jt6da|&4N$CSuzJ-^LmEMnp#N0+YtYVlwZCw&e#F9s z;z2SH(KVl@CK^Or%as@isT1i2W81}ljRLudbxaBCXP0#xDF{P8#mt>!;xN~B4t(MA zadeAPLN4kgdakh(ehtAQ2!VLC?~+bI$u)6!?(*M$j6fzc9-|vdijW4S?UIKgC14sTCWwj6@5vYuP~0sYal{^L+J@=hudK<3t z&%h(aR7#7vYjvz{$sLD-3nfuQwwU8kB1KvS*WXlC;a%b=!HK!t*_8@^TR%ZhygjX( z#{m6+HjlPjVhV@eI90`Nc1OCdL_;}&DGT3-kZwSom6Cz2UYEa0*BS04T-8gfL7&p- z@(0Sng_O&I);U`@eHw3oO}q=SK#X~kz#mR{azC=XV}=&bPnE!$K|v)QQ~psw1@8D@$U#XUTON!%M33ao0+$-58eX-56a9*DM2vQ@0E(%|GKh7GJ##EM>(q zK-@dWwk)u`40M4Qp_P-qVyv6=mbr4$TZTUhI^gRjdGic6u8`n8D!xZU9ApN=8qo`f z6kWr-==3}x$kPhZ4>y8tzms^cwyO%gi1Fb_FWQZvxSxVVzS*Blh9KwMd9iKGw#|dG zH((K7icj(G%%*TEZsD9Iz>;u~2#EFRc-|@_AE&Ud`so;M1&c1jYY-a{sWlH}4r2vYgWv+AY=oTtGY2v@ykU4k-$7Xg8=yLeUb>;I)gdpc4ZlC zjv$)&Bi?c#U%cC+bwTaog%>|;)Rx!=hQW8N#zmyONSgJ~