diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..df848a1
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,21 @@
+LITEFS_DIR="/litefs/data"
+DATABASE_PATH="./prisma/data.db"
+DATABASE_URL="file:./data.db?connection_limit=1"
+CACHE_DATABASE_PATH="./other/cache.db"
+SESSION_SECRET="super-duper-s3cret"
+HONEYPOT_SECRET="super-duper-s3cret"
+RESEND_API_KEY="re_blAh_blaHBlaHblahBLAhBlAh"
+SENTRY_DSN="your-dsn"
+
+# this is set to a random value in the Dockerfile
+INTERNAL_COMMAND_TOKEN="some-made-up-token"
+
+# the mocks and some code rely on these two being prefixed with "MOCK_"
+# if they aren't then the real github api will be attempted
+GITHUB_CLIENT_ID="MOCK_GITHUB_CLIENT_ID"
+GITHUB_CLIENT_SECRET="MOCK_GITHUB_CLIENT_SECRET"
+GITHUB_TOKEN="MOCK_GITHUB_TOKEN"
+
+# set this to false to prevent search engines from indexing the website
+# default to allow indexing for seo safety
+ALLOW_INDEXING="true"
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..84a2084
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,15 @@
+
+
+## Test Plan
+
+
+
+## Checklist
+
+- [ ] Tests updated
+- [ ] Docs updated
+
+## Screenshots
+
+
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..4b9c766
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,174 @@
+name: đ Deploy
+on:
+ push:
+ branches:
+ - main
+ - dev
+ pull_request: {}
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ actions: write
+ contents: read
+
+jobs:
+ lint:
+ name: ⏣ ESLint
+ runs-on: ubuntu-22.04
+ steps:
+ - name: âŹď¸ Checkout repo
+ uses: actions/checkout@v4
+
+ - name: â Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: đĽ Download deps
+ uses: bahmutov/npm-install@v1
+
+ - name: đź Build icons
+ run: npm run build:icons
+
+ - name: đŹ Lint
+ run: npm run lint
+
+ typecheck:
+ name: ĘŚ TypeScript
+ runs-on: ubuntu-22.04
+ steps:
+ - name: âŹď¸ Checkout repo
+ uses: actions/checkout@v4
+
+ - name: â Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: đĽ Download deps
+ uses: bahmutov/npm-install@v1
+
+ - name: đź Build icons
+ run: npm run build:icons
+
+ - name: đ Type check
+ run: npm run typecheck --if-present
+
+ vitest:
+ name: ⥠Vitest
+ runs-on: ubuntu-22.04
+ steps:
+ - name: âŹď¸ Checkout repo
+ uses: actions/checkout@v4
+
+ - name: â Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: đĽ Download deps
+ uses: bahmutov/npm-install@v1
+
+ - name: đ Copy test env vars
+ run: cp .env.example .env
+
+ - name: đź Build icons
+ run: npm run build:icons
+
+ - name: ⥠Run vitest
+ run: npm run test -- --coverage
+
+ playwright:
+ name: đ Playwright
+ runs-on: ubuntu-22.04
+ timeout-minutes: 60
+ steps:
+ - name: âŹď¸ Checkout repo
+ uses: actions/checkout@v4
+
+ - name: đ Copy test env vars
+ run: cp .env.example .env
+
+ - name: â Setup node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: đĽ Download deps
+ uses: bahmutov/npm-install@v1
+
+ - name: đĽ Install Playwright Browsers
+ run: npm run test:e2e:install
+
+ - name: đ Setup Database
+ run: npx prisma migrate deploy
+
+ - name: đŚ Cache Database
+ id: db-cache
+ uses: actions/cache@v4
+ with:
+ path: prisma/data.db
+ key:
+ db-cache-schema_${{ hashFiles('./prisma/schema.prisma')
+ }}-migrations_${{ hashFiles('./prisma/migrations/*/migration.sql')
+ }}
+
+ - name: đą Seed Database
+ if: steps.db-cache.outputs.cache-hit != 'true'
+ run: npx prisma db seed
+
+ - name: đ Build
+ run: npm run build
+
+ - name: đ Playwright tests
+ run: npx playwright test
+
+ - name: đ Upload report
+ uses: actions/upload-artifact@v4
+ if: always()
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 30
+
+ deploy:
+ name: đ Deploy
+ runs-on: ubuntu-22.04
+ needs: [lint, typecheck, vitest, playwright]
+ # only build/deploy branches on pushes
+ if: ${{ github.event_name == 'push' }}
+
+ steps:
+ - name: âŹď¸ Checkout repo
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: '50'
+
+ - name: đ Read app name
+ uses: SebRollen/toml-action@v1.2.0
+ id: app_name
+ with:
+ file: 'fly.toml'
+ field: 'app'
+
+ - name: đ Setup Fly
+ uses: superfly/flyctl-actions/setup-flyctl@1.5
+
+ - name: đ Deploy Staging
+ if: ${{ github.ref == 'refs/heads/dev' }}
+ run:
+ flyctl deploy --remote-only --build-arg COMMIT_SHA=${{ github.sha }}
+ --app ${{ steps.app_name.outputs.value }}-staging
+ env:
+ FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
+
+ - name: đ Deploy Production
+ if: ${{ github.ref == 'refs/heads/main' }}
+ run:
+ flyctl deploy --remote-only --build-arg COMMIT_SHA=${{ github.sha }}
+ --build-secret SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
+ env:
+ FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..320b1c0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+node_modules
+.DS_store
+
+/build
+/public/build
+/server-build
+.env
+.cache
+
+/prisma/data.db
+/prisma/data.db-journal
+/tests/prisma
+
+/test-results/
+/playwright-report/
+/playwright/.cache/
+/tests/fixtures/email/
+/coverage
+
+/other/cache.db
+
+# Easy way to create temporary files/folders that won't accidentally be added to git
+*.local.*
+
+# generated files
+/app/components/ui/icons
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..03d9549
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..414d4e5
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 0000000..0c83ac4
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/publicare.iml b/.idea/publicare.iml
new file mode 100644
index 0000000..24643cc
--- /dev/null
+++ b/.idea/publicare.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..668efa1
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,2 @@
+legacy-peer-deps=true
+registry=https://registry.npmjs.org/
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..f022d02
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,15 @@
+node_modules
+
+/build
+/public/build
+/server-build
+.env
+
+/test-results/
+/playwright-report/
+/playwright/.cache/
+/tests/fixtures/email/*.json
+/coverage
+/prisma/migrations
+
+package-lock.json
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..3c0a690
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,11 @@
+{
+ "recommendations": [
+ "bradlc.vscode-tailwindcss",
+ "dbaeumer.vscode-eslint",
+ "esbenp.prettier-vscode",
+ "prisma.prisma",
+ "qwtel.sqlite-viewer",
+ "yoavbls.pretty-ts-errors",
+ "github.vscode-github-actions"
+ ]
+}
diff --git a/.vscode/remix.code-snippets b/.vscode/remix.code-snippets
new file mode 100644
index 0000000..4d8ec1d
--- /dev/null
+++ b/.vscode/remix.code-snippets
@@ -0,0 +1,83 @@
+{
+ "loader": {
+ "prefix": "/loader",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "import { type LoaderFunctionArgs, json } from \"@remix-run/node\"",
+ "",
+ "export async function loader({ request }: LoaderFunctionArgs) {",
+ " return json({})",
+ "}",
+ ],
+ },
+ "action": {
+ "prefix": "/action",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "import { type ActionFunctionArgs, json } from \"@remix-run/node\"",
+ "",
+ "export async function action({ request }: ActionFunctionArgs) {",
+ " return json({})",
+ "}",
+ ],
+ },
+ "default": {
+ "prefix": "/default",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "export default function ${TM_FILENAME_BASE/[^a-zA-Z0-9]*([a-zA-Z0-9])([a-zA-Z0-9]*)/${1:/capitalize}${2}/g}() {",
+ " return (",
+ "
",
+ "
Unknown Route ",
+ " ",
+ " )",
+ "}",
+ ],
+ },
+ "headers": {
+ "prefix": "/headers",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "import type { HeadersFunction } from '@remix-run/node'",
+ "",
+ "export const headers: HeadersFunction = ({ loaderHeaders }) => ({",
+ " 'Cache-Control': loaderHeaders.get('Cache-Control') ?? '',",
+ "})",
+ ],
+ },
+ "links": {
+ "prefix": "/links",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "import type { LinksFunction } from '@remix-run/node'",
+ "",
+ "export const links: LinksFunction = () => {",
+ " return []",
+ "}",
+ ],
+ },
+ "meta": {
+ "prefix": "/meta",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "import type { MetaFunction } from '@remix-run/node'",
+ "",
+ "export const meta: MetaFunction = ({ data }) => [{",
+ " title: 'Title',",
+ "}]",
+ ],
+ },
+ "shouldRevalidate": {
+ "prefix": "/shouldRevalidate",
+ "scope": "typescriptreact,javascriptreact,typescript,javascript",
+ "body": [
+ "import type { ShouldRevalidateFunction } from '@remix-run/react'",
+ "",
+ "export const shouldRevalidate: ShouldRevalidateFunction = ({",
+ " defaultShouldRevalidate",
+ "}) => {",
+ " return defaultShouldRevalidate",
+ "}",
+ ],
+ },
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..6f6b0bf
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,17 @@
+{
+ "typescript.preferences.autoImportFileExcludePatterns": [
+ "@remix-run/server-runtime",
+ "@remix-run/router",
+ "express",
+ "@radix-ui/**",
+ "@react-email/**",
+ "react-router-dom",
+ "react-router",
+ "node:stream/consumers",
+ "node:test",
+ "node:console"
+ ],
+ "workbench.editorAssociations": {
+ "*.db": "sqlite-viewer.view"
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cc8f52f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,54 @@
+
+
+
+ Ditch analysis paralysis and start shipping Epic Web apps.
+
+
+ This is an opinionated project starter and reference that allows teams to
+ ship their ideas to production faster and on a more stable foundation based
+ on the experience of Kent C. Dodds and
+ contributors .
+
+
+
+```sh
+npx create-epic-app@latest
+```
+
+[![The Epic Stack](https://github-production-user-asset-6210df.s3.amazonaws.com/1500684/246885449-1b00286c-aa3d-44b2-9ef2-04f694eb3592.png)](https://www.epicweb.dev/epic-stack)
+
+[The Epic Stack](https://www.epicweb.dev/epic-stack)
+
+
+
+## Watch Kent's Introduction to The Epic Stack
+
+[![Epic Stack Talk slide showing Flynn Rider with knives, the text "I've been around and I've got opinions" and Kent speaking in the corner](https://github-production-user-asset-6210df.s3.amazonaws.com/1500684/277818553-47158e68-4efc-43ae-a477-9d1670d4217d.png)](https://www.epicweb.dev/talks/the-epic-stack)
+
+["The Epic Stack" by Kent C. Dodds](https://www.epicweb.dev/talks/the-epic-stack)
+
+## Docs
+
+[Read the docs](https://github.com/epicweb-dev/epic-stack/blob/main/docs)
+(please đ).
+
+## Support
+
+- đ Join the
+ [discussion on GitHub](https://github.com/epicweb-dev/epic-stack/discussions)
+ and the [KCD Community on Discord](https://kcd.im/discord).
+- đĄ Create an
+ [idea discussion](https://github.com/epicweb-dev/epic-stack/discussions/new?category=ideas)
+ for suggestions.
+- đ Open a [GitHub issue](https://github.com/epicweb-dev/epic-stack/issues) to
+ report a bug.
+
+## Branding
+
+Want to talk about the Epic Stack in a blog post or talk? Great! Here are some
+assets you can use in your material:
+[EpicWeb.dev/brand](https://epicweb.dev/brand)
+
+## Thanks
+
+You rock đި
diff --git a/app/assets/favicons/apple-touch-icon.png b/app/assets/favicons/apple-touch-icon.png
new file mode 100644
index 0000000..8bf4632
Binary files /dev/null and b/app/assets/favicons/apple-touch-icon.png differ
diff --git a/app/assets/favicons/favicon.svg b/app/assets/favicons/favicon.svg
new file mode 100644
index 0000000..72be6f0
--- /dev/null
+++ b/app/assets/favicons/favicon.svg
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/app/components/error-boundary.tsx b/app/components/error-boundary.tsx
new file mode 100644
index 0000000..573b412
--- /dev/null
+++ b/app/components/error-boundary.tsx
@@ -0,0 +1,46 @@
+import {
+ type ErrorResponse,
+ isRouteErrorResponse,
+ useParams,
+ useRouteError,
+} from '@remix-run/react'
+import { captureRemixErrorBoundaryError } from '@sentry/remix'
+import { getErrorMessage } from '#app/utils/misc.tsx'
+
+type StatusHandler = (info: {
+ error: ErrorResponse
+ params: Record
+}) => JSX.Element | null
+
+export function GeneralErrorBoundary({
+ defaultStatusHandler = ({ error }) => (
+
+ {error.status} {error.data}
+
+ ),
+ statusHandlers,
+ unexpectedErrorHandler = (error) => {getErrorMessage(error)}
,
+}: {
+ defaultStatusHandler?: StatusHandler
+ statusHandlers?: Record
+ unexpectedErrorHandler?: (error: unknown) => JSX.Element | null
+}) {
+ const error = useRouteError()
+ captureRemixErrorBoundaryError(error)
+ const params = useParams()
+
+ if (typeof document !== 'undefined') {
+ console.error(error)
+ }
+
+ return (
+
+ {isRouteErrorResponse(error)
+ ? (statusHandlers?.[error.status] ?? defaultStatusHandler)({
+ error,
+ params,
+ })
+ : unexpectedErrorHandler(error)}
+
+ )
+}
diff --git a/app/components/floating-toolbar.tsx b/app/components/floating-toolbar.tsx
new file mode 100644
index 0000000..41b5be0
--- /dev/null
+++ b/app/components/floating-toolbar.tsx
@@ -0,0 +1,2 @@
+export const floatingToolbarClassName =
+ 'absolute bottom-3 left-3 right-3 flex items-center gap-2 rounded-lg bg-muted/80 p-4 pl-5 shadow-xl shadow-accent backdrop-blur-sm md:gap-4 md:pl-7 justify-end'
diff --git a/app/components/forms.tsx b/app/components/forms.tsx
new file mode 100644
index 0000000..f396e9f
--- /dev/null
+++ b/app/components/forms.tsx
@@ -0,0 +1,202 @@
+import { useInputControl } from '@conform-to/react'
+import { REGEXP_ONLY_DIGITS_AND_CHARS, type OTPInputProps } from 'input-otp'
+import React, { useId } from 'react'
+import { Checkbox, type CheckboxProps } from './ui/checkbox.tsx'
+import {
+ InputOTP,
+ InputOTPGroup,
+ InputOTPSeparator,
+ InputOTPSlot,
+} from './ui/input-otp.tsx'
+import { Input } from './ui/input.tsx'
+import { Label } from './ui/label.tsx'
+import { Textarea } from './ui/textarea.tsx'
+
+export type ListOfErrors = Array | null | undefined
+
+export function ErrorList({
+ id,
+ errors,
+}: {
+ errors?: ListOfErrors
+ id?: string
+}) {
+ const errorsToRender = errors?.filter(Boolean)
+ if (!errorsToRender?.length) return null
+ return (
+
+ {errorsToRender.map((e) => (
+
+ {e}
+
+ ))}
+
+ )
+}
+
+export function Field({
+ labelProps,
+ inputProps,
+ errors,
+ className,
+}: {
+ labelProps: React.LabelHTMLAttributes
+ inputProps: React.InputHTMLAttributes
+ errors?: ListOfErrors
+ className?: string
+}) {
+ const fallbackId = useId()
+ const id = inputProps.id ?? fallbackId
+ const errorId = errors?.length ? `${id}-error` : undefined
+ return (
+
+
+
+
+ {errorId ? : null}
+
+
+ )
+}
+
+export function OTPField({
+ labelProps,
+ inputProps,
+ errors,
+ className,
+}: {
+ labelProps: React.LabelHTMLAttributes
+ inputProps: Partial
+ errors?: ListOfErrors
+ className?: string
+}) {
+ const fallbackId = useId()
+ const id = inputProps.id ?? fallbackId
+ const errorId = errors?.length ? `${id}-error` : undefined
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {errorId ? : null}
+
+
+ )
+}
+
+export function TextareaField({
+ labelProps,
+ textareaProps,
+ errors,
+ className,
+}: {
+ labelProps: React.LabelHTMLAttributes
+ textareaProps: React.TextareaHTMLAttributes
+ errors?: ListOfErrors
+ className?: string
+}) {
+ const fallbackId = useId()
+ const id = textareaProps.id ?? textareaProps.name ?? fallbackId
+ const errorId = errors?.length ? `${id}-error` : undefined
+ return (
+
+
+
+
+ {errorId ? : null}
+
+
+ )
+}
+
+export function CheckboxField({
+ labelProps,
+ buttonProps,
+ errors,
+ className,
+}: {
+ labelProps: JSX.IntrinsicElements['label']
+ buttonProps: CheckboxProps & {
+ name: string
+ form: string
+ value?: string
+ }
+ errors?: ListOfErrors
+ className?: string
+}) {
+ const { key, defaultChecked, ...checkboxProps } = buttonProps
+ const fallbackId = useId()
+ const checkedValue = buttonProps.value ?? 'on'
+ const input = useInputControl({
+ key,
+ name: buttonProps.name,
+ formId: buttonProps.form,
+ initialValue: defaultChecked ? checkedValue : undefined,
+ })
+ const id = buttonProps.id ?? fallbackId
+ const errorId = errors?.length ? `${id}-error` : undefined
+
+ return (
+
+
+ {
+ input.change(state.valueOf() ? checkedValue : '')
+ buttonProps.onCheckedChange?.(state)
+ }}
+ onFocus={(event) => {
+ input.focus()
+ buttonProps.onFocus?.(event)
+ }}
+ onBlur={(event) => {
+ input.blur()
+ buttonProps.onBlur?.(event)
+ }}
+ type="button"
+ />
+
+
+
+ {errorId ? : null}
+
+
+ )
+}
diff --git a/app/components/progress-bar.tsx b/app/components/progress-bar.tsx
new file mode 100644
index 0000000..00737ae
--- /dev/null
+++ b/app/components/progress-bar.tsx
@@ -0,0 +1,63 @@
+import { useNavigation } from '@remix-run/react'
+import { useEffect, useRef, useState } from 'react'
+import { useSpinDelay } from 'spin-delay'
+import { cn } from '#app/utils/misc.tsx'
+import { Icon } from './ui/icon.tsx'
+
+function EpicProgress() {
+ const transition = useNavigation()
+ const busy = transition.state !== 'idle'
+ const delayedPending = useSpinDelay(busy, {
+ delay: 600,
+ minDuration: 400,
+ })
+ const ref = useRef(null)
+ const [animationComplete, setAnimationComplete] = useState(true)
+
+ useEffect(() => {
+ if (!ref.current) return
+ if (delayedPending) setAnimationComplete(false)
+
+ const animationPromises = ref.current
+ .getAnimations()
+ .map(({ finished }) => finished)
+
+ void Promise.allSettled(animationPromises).then(() => {
+ if (!delayedPending) setAnimationComplete(true)
+ })
+ }, [delayedPending])
+
+ return (
+
+
+ {delayedPending && (
+
+
+
+ )}
+
+ )
+}
+
+export { EpicProgress }
diff --git a/app/components/search-bar.tsx b/app/components/search-bar.tsx
new file mode 100644
index 0000000..30c77d3
--- /dev/null
+++ b/app/components/search-bar.tsx
@@ -0,0 +1,63 @@
+import { Form, useSearchParams, useSubmit } from '@remix-run/react'
+import { useId } from 'react'
+import { useDebounce, useIsPending } from '#app/utils/misc.tsx'
+import { Icon } from './ui/icon.tsx'
+import { Input } from './ui/input.tsx'
+import { Label } from './ui/label.tsx'
+import { StatusButton } from './ui/status-button.tsx'
+
+export function SearchBar({
+ status,
+ autoFocus = false,
+ autoSubmit = false,
+}: {
+ status: 'idle' | 'pending' | 'success' | 'error'
+ autoFocus?: boolean
+ autoSubmit?: boolean
+}) {
+ const id = useId()
+ const [searchParams] = useSearchParams()
+ const submit = useSubmit()
+ const isSubmitting = useIsPending({
+ formMethod: 'GET',
+ formAction: '/users',
+ })
+
+ const handleFormChange = useDebounce((form: HTMLFormElement) => {
+ submit(form)
+ }, 400)
+
+ return (
+
+ )
+}
diff --git a/app/components/spacer.tsx b/app/components/spacer.tsx
new file mode 100644
index 0000000..8a8e537
--- /dev/null
+++ b/app/components/spacer.tsx
@@ -0,0 +1,57 @@
+export function Spacer({
+ size,
+}: {
+ /**
+ * The size of the space
+ *
+ * 4xs: h-4 (16px)
+ *
+ * 3xs: h-8 (32px)
+ *
+ * 2xs: h-12 (48px)
+ *
+ * xs: h-16 (64px)
+ *
+ * sm: h-20 (80px)
+ *
+ * md: h-24 (96px)
+ *
+ * lg: h-28 (112px)
+ *
+ * xl: h-32 (128px)
+ *
+ * 2xl: h-36 (144px)
+ *
+ * 3xl: h-40 (160px)
+ *
+ * 4xl: h-44 (176px)
+ */
+ size:
+ | '4xs'
+ | '3xs'
+ | '2xs'
+ | 'xs'
+ | 'sm'
+ | 'md'
+ | 'lg'
+ | 'xl'
+ | '2xl'
+ | '3xl'
+ | '4xl'
+}) {
+ const options: Record = {
+ '4xs': 'h-4',
+ '3xs': 'h-8',
+ '2xs': 'h-12',
+ xs: 'h-16',
+ sm: 'h-20',
+ md: 'h-24',
+ lg: 'h-28',
+ xl: 'h-32',
+ '2xl': 'h-36',
+ '3xl': 'h-40',
+ '4xl': 'h-44',
+ }
+ const className = options[size]
+ return
+}
diff --git a/app/components/toaster.tsx b/app/components/toaster.tsx
new file mode 100644
index 0000000..954b2db
--- /dev/null
+++ b/app/components/toaster.tsx
@@ -0,0 +1,16 @@
+import { useEffect } from 'react'
+import { toast as showToast } from 'sonner'
+import { type Toast } from '#app/utils/toast.server.ts'
+
+export function useToast(toast?: Toast | null) {
+ useEffect(() => {
+ if (toast) {
+ setTimeout(() => {
+ showToast[toast.type](toast.title, {
+ id: toast.id,
+ description: toast.description,
+ })
+ }, 0)
+ }
+ }, [toast])
+}
diff --git a/app/components/ui/README.md b/app/components/ui/README.md
new file mode 100644
index 0000000..433847d
--- /dev/null
+++ b/app/components/ui/README.md
@@ -0,0 +1,7 @@
+# shadcn/ui
+
+Some components in this directory are downloaded via the
+[shadcn/ui](https://ui.shadcn.com) [CLI](https://ui.shadcn.com/docs/cli). Feel
+free to customize them to your needs. It's important to know that shadcn/ui is
+not a library of components you install, but instead it's a registry of prebuilt
+components which you can download and customize.
diff --git a/app/components/ui/badge.tsx b/app/components/ui/badge.tsx
new file mode 100644
index 0000000..211ea9f
--- /dev/null
+++ b/app/components/ui/badge.tsx
@@ -0,0 +1,36 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "#app/utils/misc.tsx"
+
+const badgeVariants = cva(
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus: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 interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ )
+}
+
+export { Badge, badgeVariants }
diff --git a/app/components/ui/button.tsx b/app/components/ui/button.tsx
new file mode 100644
index 0000000..36601c5
--- /dev/null
+++ b/app/components/ui/button.tsx
@@ -0,0 +1,58 @@
+import { Slot } from '@radix-ui/react-slot'
+import { cva, type VariantProps } from 'class-variance-authority'
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+const buttonVariants = cva(
+ 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors outline-none focus-visible:ring-2 focus-within:ring-2 ring-ring ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
+ {
+ variants: {
+ variant: {
+ default: 'bg-primary text-primary-foreground hover:bg-primary/80',
+ destructive:
+ 'bg-destructive text-destructive-foreground hover:bg-destructive/80',
+ 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',
+ wide: 'px-24 py-5',
+ sm: 'h-9 rounded-md px-3',
+ lg: 'h-11 rounded-md px-8',
+ pill: 'px-12 py-3 leading-3',
+ icon: 'h-10 w-10',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default',
+ },
+ },
+)
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : 'button'
+ return (
+
+ )
+ },
+)
+Button.displayName = 'Button'
+
+export { Button, buttonVariants }
diff --git a/app/components/ui/checkbox.tsx b/app/components/ui/checkbox.tsx
new file mode 100644
index 0000000..637a7fd
--- /dev/null
+++ b/app/components/ui/checkbox.tsx
@@ -0,0 +1,41 @@
+import * as CheckboxPrimitive from '@radix-ui/react-checkbox'
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+export type CheckboxProps = Omit<
+ React.ComponentPropsWithoutRef,
+ 'type'
+> & {
+ type?: string
+}
+
+const Checkbox = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+
+
+
+
+))
+Checkbox.displayName = CheckboxPrimitive.Root.displayName
+
+export { Checkbox }
diff --git a/app/components/ui/dropdown-menu.tsx b/app/components/ui/dropdown-menu.tsx
new file mode 100644
index 0000000..3bb4fe3
--- /dev/null
+++ b/app/components/ui/dropdown-menu.tsx
@@ -0,0 +1,206 @@
+import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+const DropdownMenu = DropdownMenuPrimitive.Root
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+ âśď¸
+
+))
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ âŞ
+
+
+ {children}
+
+))
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+}
diff --git a/app/components/ui/icon.tsx b/app/components/ui/icon.tsx
new file mode 100644
index 0000000..10b8c1d
--- /dev/null
+++ b/app/components/ui/icon.tsx
@@ -0,0 +1,77 @@
+import { type SVGProps } from 'react'
+import { cn } from '#app/utils/misc.tsx'
+import href from './icons/sprite.svg'
+import { type IconName } from '@/icon-name'
+
+export { href }
+export { IconName }
+
+const sizeClassName = {
+ font: 'w-[1em] h-[1em]',
+ xs: 'w-3 h-3',
+ sm: 'w-4 h-4',
+ md: 'w-5 h-5',
+ lg: 'w-6 h-6',
+ xl: 'w-7 h-7',
+} as const
+
+type Size = keyof typeof sizeClassName
+
+const childrenSizeClassName = {
+ font: 'gap-1.5',
+ xs: 'gap-1.5',
+ sm: 'gap-1.5',
+ md: 'gap-2',
+ lg: 'gap-2',
+ xl: 'gap-3',
+} satisfies Record
+
+/**
+ * Renders an SVG icon. The icon defaults to the size of the font. To make it
+ * align vertically with neighboring text, you can pass the text as a child of
+ * the icon and it will be automatically aligned.
+ * Alternatively, if you're not ok with the icon being to the left of the text,
+ * you need to wrap the icon and text in a common parent and set the parent to
+ * display "flex" (or "inline-flex") with "items-center" and a reasonable gap.
+ *
+ * Pass `title` prop to the `Icon` component to get `` element rendered
+ * in the SVG container, providing this way for accessibility.
+ */
+export function Icon({
+ name,
+ size = 'font',
+ className,
+ title,
+ children,
+ ...props
+}: SVGProps & {
+ name: IconName
+ size?: Size
+ title?: string
+}) {
+ if (children) {
+ return (
+
+
+ {children}
+
+ )
+ }
+ return (
+
+ {title ? {title} : null}
+
+
+ )
+}
diff --git a/app/components/ui/input-otp.tsx b/app/components/ui/input-otp.tsx
new file mode 100644
index 0000000..ff7a2d7
--- /dev/null
+++ b/app/components/ui/input-otp.tsx
@@ -0,0 +1,70 @@
+import { OTPInput, OTPInputContext } from 'input-otp'
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+const InputOTP = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, containerClassName, ...props }, ref) => (
+
+))
+InputOTP.displayName = 'InputOTP'
+
+const InputOTPGroup = React.forwardRef<
+ React.ElementRef<'div'>,
+ React.ComponentPropsWithoutRef<'div'>
+>(({ className, ...props }, ref) => (
+
+))
+InputOTPGroup.displayName = 'InputOTPGroup'
+
+const InputOTPSlot = React.forwardRef<
+ React.ElementRef<'div'>,
+ React.ComponentPropsWithoutRef<'div'> & { index: number }
+>(({ index, className, ...props }, ref) => {
+ const inputOTPContext = React.useContext(OTPInputContext)
+ const slot = inputOTPContext.slots[index]
+ if (!slot) throw new Error('Invalid slot index')
+ const { char, hasFakeCaret, isActive } = slot
+
+ return (
+
+ {char}
+ {hasFakeCaret && (
+
+ )}
+
+ )
+})
+InputOTPSlot.displayName = 'InputOTPSlot'
+
+const InputOTPSeparator = React.forwardRef<
+ React.ElementRef<'div'>,
+ React.ComponentPropsWithoutRef<'div'>
+>(({ ...props }, ref) => (
+
+ -
+
+))
+InputOTPSeparator.displayName = 'InputOTPSeparator'
+
+export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }
diff --git a/app/components/ui/input.tsx b/app/components/ui/input.tsx
new file mode 100644
index 0000000..f4b2db3
--- /dev/null
+++ b/app/components/ui/input.tsx
@@ -0,0 +1,25 @@
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+export interface InputProps
+ extends React.InputHTMLAttributes {}
+
+const Input = React.forwardRef(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ )
+ },
+)
+Input.displayName = 'Input'
+
+export { Input }
diff --git a/app/components/ui/label.tsx b/app/components/ui/label.tsx
new file mode 100644
index 0000000..ec453ee
--- /dev/null
+++ b/app/components/ui/label.tsx
@@ -0,0 +1,24 @@
+import * as LabelPrimitive from '@radix-ui/react-label'
+import { cva, type VariantProps } from 'class-variance-authority'
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+const labelVariants = cva(
+ 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
+)
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+))
+Label.displayName = LabelPrimitive.Root.displayName
+
+export { Label }
diff --git a/app/components/ui/sonner.tsx b/app/components/ui/sonner.tsx
new file mode 100644
index 0000000..029a2a4
--- /dev/null
+++ b/app/components/ui/sonner.tsx
@@ -0,0 +1,26 @@
+import { Toaster as Sonner } from 'sonner'
+
+type ToasterProps = React.ComponentProps
+
+const EpicToaster = ({ theme, ...props }: ToasterProps) => {
+ return (
+
+ )
+}
+
+export { EpicToaster }
diff --git a/app/components/ui/status-button.tsx b/app/components/ui/status-button.tsx
new file mode 100644
index 0000000..f39a7ff
--- /dev/null
+++ b/app/components/ui/status-button.tsx
@@ -0,0 +1,78 @@
+import * as React from 'react'
+import { useSpinDelay } from 'spin-delay'
+import { cn } from '#app/utils/misc.tsx'
+import { Button, type ButtonProps } from './button.tsx'
+import { Icon } from './icon.tsx'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from './tooltip.tsx'
+
+export const StatusButton = React.forwardRef<
+ HTMLButtonElement,
+ ButtonProps & {
+ status: 'pending' | 'success' | 'error' | 'idle'
+ message?: string | null
+ spinDelay?: Parameters[1]
+ }
+>(({ message, status, className, children, spinDelay, ...props }, ref) => {
+ const delayedPending = useSpinDelay(status === 'pending', {
+ delay: 400,
+ minDuration: 300,
+ ...spinDelay,
+ })
+ const companion = {
+ pending: delayedPending ? (
+
+
+
+ ) : null,
+ success: (
+
+
+
+ ),
+ error: (
+
+
+
+ ),
+ idle: null,
+ }[status]
+
+ return (
+
+ {children}
+ {message ? (
+
+
+ {companion}
+ {message}
+
+
+ ) : (
+ companion
+ )}
+
+ )
+})
+StatusButton.displayName = 'Button'
diff --git a/app/components/ui/table.tsx b/app/components/ui/table.tsx
new file mode 100644
index 0000000..ba98722
--- /dev/null
+++ b/app/components/ui/table.tsx
@@ -0,0 +1,117 @@
+import * as React from "react"
+
+import { cn } from "#app/utils/misc.tsx"
+
+const Table = React.forwardRef<
+ HTMLTableElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Table.displayName = "Table"
+
+const TableHeader = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableHeader.displayName = "TableHeader"
+
+const TableBody = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableBody.displayName = "TableBody"
+
+const TableFooter = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+ tr]:last:border-b-0",
+ className
+ )}
+ {...props}
+ />
+))
+TableFooter.displayName = "TableFooter"
+
+const TableRow = React.forwardRef<
+ HTMLTableRowElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableRow.displayName = "TableRow"
+
+const TableHead = React.forwardRef<
+ HTMLTableCellElement,
+ React.ThHTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableHead.displayName = "TableHead"
+
+const TableCell = React.forwardRef<
+ HTMLTableCellElement,
+ React.TdHTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableCell.displayName = "TableCell"
+
+const TableCaption = React.forwardRef<
+ HTMLTableCaptionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableCaption.displayName = "TableCaption"
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+}
diff --git a/app/components/ui/textarea.tsx b/app/components/ui/textarea.tsx
new file mode 100644
index 0000000..4232b9e
--- /dev/null
+++ b/app/components/ui/textarea.tsx
@@ -0,0 +1,24 @@
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+export interface TextareaProps
+ extends React.TextareaHTMLAttributes {}
+
+const Textarea = React.forwardRef(
+ ({ className, ...props }, ref) => {
+ return (
+
+ )
+ },
+)
+Textarea.displayName = 'Textarea'
+
+export { Textarea }
diff --git a/app/components/ui/tooltip.tsx b/app/components/ui/tooltip.tsx
new file mode 100644
index 0000000..5017f3e
--- /dev/null
+++ b/app/components/ui/tooltip.tsx
@@ -0,0 +1,28 @@
+import * as TooltipPrimitive from '@radix-ui/react-tooltip'
+import * as React from 'react'
+
+import { cn } from '#app/utils/misc.tsx'
+
+const TooltipProvider = TooltipPrimitive.Provider
+
+const Tooltip = TooltipPrimitive.Root
+
+const TooltipTrigger = TooltipPrimitive.Trigger
+
+const TooltipContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+))
+TooltipContent.displayName = TooltipPrimitive.Content.displayName
+
+export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
diff --git a/app/entry.client.tsx b/app/entry.client.tsx
new file mode 100644
index 0000000..cef8316
--- /dev/null
+++ b/app/entry.client.tsx
@@ -0,0 +1,11 @@
+import { RemixBrowser } from '@remix-run/react'
+import { startTransition } from 'react'
+import { hydrateRoot } from 'react-dom/client'
+
+if (ENV.MODE === 'production' && ENV.SENTRY_DSN) {
+ void import('./utils/monitoring.client.tsx').then(({ init }) => init())
+}
+
+startTransition(() => {
+ hydrateRoot(document, )
+})
diff --git a/app/entry.server.tsx b/app/entry.server.tsx
new file mode 100644
index 0000000..ed4e4b8
--- /dev/null
+++ b/app/entry.server.tsx
@@ -0,0 +1,116 @@
+import { PassThrough } from 'node:stream'
+import {
+ createReadableStreamFromReadable,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+ type HandleDocumentRequestFunction,
+} from '@remix-run/node'
+import { RemixServer } from '@remix-run/react'
+import * as Sentry from '@sentry/remix'
+import chalk from 'chalk'
+import { isbot } from 'isbot'
+import { renderToPipeableStream } from 'react-dom/server'
+import { getEnv, init } from './utils/env.server.ts'
+import { getInstanceInfo } from './utils/litefs.server.ts'
+import { NonceProvider } from './utils/nonce-provider.ts'
+import { makeTimings } from './utils/timing.server.ts'
+
+const ABORT_DELAY = 5000
+
+init()
+global.ENV = getEnv()
+
+type DocRequestArgs = Parameters
+
+export default async function handleRequest(...args: DocRequestArgs) {
+ const [
+ request,
+ responseStatusCode,
+ responseHeaders,
+ remixContext,
+ loadContext,
+ ] = args
+ const { currentInstance, primaryInstance } = await getInstanceInfo()
+ responseHeaders.set('fly-region', process.env.FLY_REGION ?? 'unknown')
+ responseHeaders.set('fly-app', process.env.FLY_APP_NAME ?? 'unknown')
+ responseHeaders.set('fly-primary-instance', primaryInstance)
+ responseHeaders.set('fly-instance', currentInstance)
+
+ if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) {
+ responseHeaders.append('Document-Policy', 'js-profiling')
+ }
+
+ const callbackName = isbot(request.headers.get('user-agent'))
+ ? 'onAllReady'
+ : 'onShellReady'
+
+ const nonce = loadContext.cspNonce?.toString() ?? ''
+ return new Promise(async (resolve, reject) => {
+ let didError = false
+ // NOTE: this timing will only include things that are rendered in the shell
+ // and will not include suspended components and deferred loaders
+ const timings = makeTimings('render', 'renderToPipeableStream')
+
+ const { pipe, abort } = renderToPipeableStream(
+
+
+ ,
+ {
+ [callbackName]: () => {
+ const body = new PassThrough()
+ responseHeaders.set('Content-Type', 'text/html')
+ responseHeaders.append('Server-Timing', timings.toString())
+ resolve(
+ new Response(createReadableStreamFromReadable(body), {
+ headers: responseHeaders,
+ status: didError ? 500 : responseStatusCode,
+ }),
+ )
+ pipe(body)
+ },
+ onShellError: (err: unknown) => {
+ reject(err)
+ },
+ onError: () => {
+ didError = true
+ },
+ nonce,
+ },
+ )
+
+ setTimeout(abort, ABORT_DELAY)
+ })
+}
+
+export async function handleDataRequest(response: Response) {
+ const { currentInstance, primaryInstance } = await getInstanceInfo()
+ response.headers.set('fly-region', process.env.FLY_REGION ?? 'unknown')
+ response.headers.set('fly-app', process.env.FLY_APP_NAME ?? 'unknown')
+ response.headers.set('fly-primary-instance', primaryInstance)
+ response.headers.set('fly-instance', currentInstance)
+
+ return response
+}
+
+export function handleError(
+ error: unknown,
+ { request }: LoaderFunctionArgs | ActionFunctionArgs,
+): void {
+ // Skip capturing if the request is aborted as Remix docs suggest
+ // Ref: https://remix.run/docs/en/main/file-conventions/entry.server#handleerror
+ if (request.signal.aborted) {
+ return
+ }
+ if (error instanceof Error) {
+ console.error(chalk.red(error.stack))
+ void Sentry.captureRemixServerException(
+ error,
+ 'remix.server',
+ request,
+ true,
+ )
+ } else {
+ console.error(error)
+ Sentry.captureException(error)
+ }
+}
diff --git a/app/root.tsx b/app/root.tsx
new file mode 100644
index 0000000..af99a6b
--- /dev/null
+++ b/app/root.tsx
@@ -0,0 +1,333 @@
+import {
+ json,
+ type LoaderFunctionArgs,
+ type HeadersFunction,
+ type LinksFunction,
+ type MetaFunction,
+} from '@remix-run/node'
+import {
+ Form,
+ Link,
+ Links,
+ Meta,
+ Outlet,
+ Scripts,
+ ScrollRestoration,
+ useLoaderData,
+ useMatches,
+ useSubmit,
+} from '@remix-run/react'
+import { withSentry } from '@sentry/remix'
+import { useRef } from 'react'
+import { HoneypotProvider } from 'remix-utils/honeypot/react'
+import appleTouchIconAssetUrl from './assets/favicons/apple-touch-icon.png'
+import faviconAssetUrl from './assets/favicons/favicon.svg'
+import { GeneralErrorBoundary } from './components/error-boundary.tsx'
+import { EpicProgress } from './components/progress-bar.tsx'
+import { SearchBar } from './components/search-bar.tsx'
+import { useToast } from './components/toaster.tsx'
+import { Button } from './components/ui/button.tsx'
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuPortal,
+ DropdownMenuTrigger,
+} from './components/ui/dropdown-menu.tsx'
+import { Icon, href as iconsHref } from './components/ui/icon.tsx'
+import { EpicToaster } from './components/ui/sonner.tsx'
+import { ThemeSwitch, useTheme } from './routes/resources+/theme-switch.tsx'
+import tailwindStyleSheetUrl from './styles/tailwind.css?url'
+import { getUserId, logout } from './utils/auth.server.ts'
+import { ClientHintCheck, getHints } from './utils/client-hints.tsx'
+import { prisma } from './utils/db.server.ts'
+import { getEnv } from './utils/env.server.ts'
+import { honeypot } from './utils/honeypot.server.ts'
+import { combineHeaders, getDomainUrl, getUserImgSrc } from './utils/misc.tsx'
+import { useNonce } from './utils/nonce-provider.ts'
+import { type Theme, getTheme } from './utils/theme.server.ts'
+import { makeTimings, time } from './utils/timing.server.ts'
+import { getToast } from './utils/toast.server.ts'
+import { useOptionalUser, useUser } from './utils/user.ts'
+
+export const links: LinksFunction = () => {
+ return [
+ // Preload svg sprite as a resource to avoid render blocking
+ { rel: 'preload', href: iconsHref, as: 'image' },
+ {
+ rel: 'icon',
+ href: '/favicon.ico',
+ sizes: '48x48',
+ },
+ { rel: 'icon', type: 'image/svg+xml', href: faviconAssetUrl },
+ { rel: 'apple-touch-icon', href: appleTouchIconAssetUrl },
+ {
+ rel: 'manifest',
+ href: '/site.webmanifest',
+ crossOrigin: 'use-credentials',
+ } as const, // necessary to make typescript happy
+ { rel: 'stylesheet', href: tailwindStyleSheetUrl },
+ ].filter(Boolean)
+}
+
+export const meta: MetaFunction = ({ data }) => {
+ return [
+ { title: data ? 'Publicare' : 'Error | Publicare' },
+ { name: 'description', content: `` },
+ ]
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const timings = makeTimings('root loader')
+ const userId = await time(() => getUserId(request), {
+ timings,
+ type: 'getUserId',
+ desc: 'getUserId in root',
+ })
+
+ const user = userId
+ ? await time(
+ () =>
+ prisma.user.findUniqueOrThrow({
+ select: {
+ id: true,
+ name: true,
+ username: true,
+ image: { select: { id: true } },
+ roles: {
+ select: {
+ name: true,
+ permissions: {
+ select: { entity: true, action: true, access: true },
+ },
+ },
+ },
+ },
+ where: { id: userId },
+ }),
+ { timings, type: 'find user', desc: 'find user in root' },
+ )
+ : null
+ if (userId && !user) {
+ console.info('something weird happened')
+ // something weird happened... The user is authenticated but we can't find
+ // them in the database. Maybe they were deleted? Let's log them out.
+ await logout({ request, redirectTo: '/' })
+ }
+ const { toast, headers: toastHeaders } = await getToast(request)
+ const honeyProps = honeypot.getInputProps()
+
+ return json(
+ {
+ user,
+ requestInfo: {
+ hints: getHints(request),
+ origin: getDomainUrl(request),
+ path: new URL(request.url).pathname,
+ userPrefs: {
+ theme: getTheme(request),
+ },
+ },
+ ENV: getEnv(),
+ toast,
+ honeyProps,
+ },
+ {
+ headers: combineHeaders(
+ { 'Server-Timing': timings.toString() },
+ toastHeaders,
+ ),
+ },
+ )
+}
+
+export const headers: HeadersFunction = ({ loaderHeaders }) => {
+ const headers = {
+ 'Server-Timing': loaderHeaders.get('Server-Timing') ?? '',
+ }
+ return headers
+}
+
+function Document({
+ children,
+ nonce,
+ theme = 'light',
+ env = {},
+ allowIndexing = true,
+}: {
+ children: React.ReactNode
+ nonce: string
+ theme?: Theme
+ env?: Record
+ allowIndexing?: boolean
+}) {
+ return (
+
+
+
+
+
+
+ {allowIndexing ? null : (
+
+ )}
+
+
+
+ {children}
+
+
+
+
+
+ )
+}
+
+function App() {
+ const data = useLoaderData()
+ const nonce = useNonce()
+ const user = useOptionalUser()
+ const theme = useTheme()
+ const matches = useMatches()
+ const isOnSearchPage = matches.find((m) => m.id === 'routes/users+/index')
+ const searchBar = isOnSearchPage ? null :
+ const allowIndexing = data.ENV.ALLOW_INDEXING !== 'false'
+ useToast(data.toast)
+
+ return (
+
+
+
+
+
+ )
+}
+
+function Logo() {
+ return (
+
+
+ publicare
+
+
+ tool
+
+
+ )
+}
+
+function AppWithProviders() {
+ const data = useLoaderData()
+ return (
+
+
+
+ )
+}
+
+export default withSentry(AppWithProviders)
+
+function UserDropdown() {
+ const user = useUser()
+ const submit = useSubmit()
+ const formRef = useRef(null)
+ return (
+
+
+
+ e.preventDefault()}
+ className="flex items-center gap-2"
+ >
+
+
+ {user.name ?? user.username}
+
+
+
+
+
+
+
+
+
+ Profile
+
+
+
+
+
+
+ Notes
+
+
+
+ {
+ event.preventDefault()
+ submit(formRef.current)
+ }}
+ >
+
+
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ // the nonce doesn't rely on the loader so we can access that
+ const nonce = useNonce()
+
+ // NOTE: you cannot use useLoaderData in an ErrorBoundary because the loader
+ // likely failed to run so we have to do the best we can.
+ // We could probably do better than this (it's possible the loader did run).
+ // This would require a change in Remix.
+
+ // Just make sure your root route never errors out and you'll always be able
+ // to give the user a better UX.
+
+ return (
+
+
+
+ )
+}
diff --git a/app/routes/$.tsx b/app/routes/$.tsx
new file mode 100644
index 0000000..b26d52a
--- /dev/null
+++ b/app/routes/$.tsx
@@ -0,0 +1,43 @@
+// This is called a "splat route" and as it's in the root `/app/routes/`
+// directory, it's a catchall. If no other routes match, this one will and we
+// can know that the user is hitting a URL that doesn't exist. By throwing a
+// 404 from the loader, we can force the error boundary to render which will
+// ensure the user gets the right status code and we can display a nicer error
+// message for them than the Remix and/or browser default.
+
+import { Link, useLocation } from '@remix-run/react'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+
+export async function loader() {
+ throw new Response('Not found', { status: 404 })
+}
+
+export default function NotFound() {
+ // due to the loader, this component will never be rendered, but we'll return
+ // the error boundary just in case.
+ return
+}
+
+export function ErrorBoundary() {
+ const location = useLocation()
+ return (
+ (
+
+
+
We can't find this page:
+
+ {location.pathname}
+
+
+
+
Back to home
+
+
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/_auth+/auth.$provider.callback.test.ts b/app/routes/_auth+/auth.$provider.callback.test.ts
new file mode 100644
index 0000000..0882304
--- /dev/null
+++ b/app/routes/_auth+/auth.$provider.callback.test.ts
@@ -0,0 +1,259 @@
+import { invariant } from '@epic-web/invariant'
+import { faker } from '@faker-js/faker'
+import { http } from 'msw'
+import { afterEach, expect, test } from 'vitest'
+import { twoFAVerificationType } from '#app/routes/settings+/profile.two-factor.tsx'
+import { getSessionExpirationDate, sessionKey } from '#app/utils/auth.server.ts'
+import { connectionSessionStorage } from '#app/utils/connections.server.ts'
+import { GITHUB_PROVIDER_NAME } from '#app/utils/connections.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { generateTOTP } from '#app/utils/totp.server.ts'
+import { createUser } from '#tests/db-utils.ts'
+import { insertGitHubUser, deleteGitHubUsers } from '#tests/mocks/github.ts'
+import { server } from '#tests/mocks/index.ts'
+import { consoleError } from '#tests/setup/setup-test-env.ts'
+import { BASE_URL, convertSetCookieToCookie } from '#tests/utils.ts'
+import { loader } from './auth.$provider.callback.ts'
+
+const ROUTE_PATH = '/auth/github/callback'
+const PARAMS = { provider: 'github' }
+
+afterEach(async () => {
+ await deleteGitHubUsers()
+})
+
+test('a new user goes to onboarding', async () => {
+ const request = await setupRequest()
+ const response = await loader({ request, params: PARAMS, context: {} }).catch(
+ (e) => e,
+ )
+ expect(response).toHaveRedirect('/onboarding/github')
+})
+
+test('when auth fails, send the user to login with a toast', async () => {
+ consoleError.mockImplementation(() => {})
+ server.use(
+ http.post('https://github.com/login/oauth/access_token', async () => {
+ return new Response('error', { status: 400 })
+ }),
+ )
+ const request = await setupRequest()
+ const response = await loader({ request, params: PARAMS, context: {} }).catch(
+ (e) => e,
+ )
+ invariant(response instanceof Response, 'response should be a Response')
+ expect(response).toHaveRedirect('/login')
+ await expect(response).toSendToast(
+ expect.objectContaining({
+ title: 'Auth Failed',
+ type: 'error',
+ }),
+ )
+ expect(consoleError).toHaveBeenCalledTimes(1)
+})
+
+test('when a user is logged in, it creates the connection', async () => {
+ const githubUser = await insertGitHubUser()
+ const session = await setupUser()
+ const request = await setupRequest({
+ sessionId: session.id,
+ code: githubUser.code,
+ })
+ const response = await loader({ request, params: PARAMS, context: {} })
+ expect(response).toHaveRedirect('/settings/profile/connections')
+ await expect(response).toSendToast(
+ expect.objectContaining({
+ title: 'Connected',
+ type: 'success',
+ description: expect.stringContaining(githubUser.profile.login),
+ }),
+ )
+ const connection = await prisma.connection.findFirst({
+ select: { id: true },
+ where: {
+ userId: session.userId,
+ providerId: githubUser.profile.id.toString(),
+ },
+ })
+ expect(
+ connection,
+ 'the connection was not created in the database',
+ ).toBeTruthy()
+})
+
+test(`when a user is logged in and has already connected, it doesn't do anything and just redirects the user back to the connections page`, async () => {
+ const session = await setupUser()
+ const githubUser = await insertGitHubUser()
+ await prisma.connection.create({
+ data: {
+ providerName: GITHUB_PROVIDER_NAME,
+ userId: session.userId,
+ providerId: githubUser.profile.id.toString(),
+ },
+ })
+ const request = await setupRequest({
+ sessionId: session.id,
+ code: githubUser.code,
+ })
+ const response = await loader({ request, params: PARAMS, context: {} })
+ expect(response).toHaveRedirect('/settings/profile/connections')
+ await expect(response).toSendToast(
+ expect.objectContaining({
+ title: 'Already Connected',
+ description: expect.stringContaining(githubUser.profile.login),
+ }),
+ )
+})
+
+test('when a user exists with the same email, create connection and make session', async () => {
+ const githubUser = await insertGitHubUser()
+ const email = githubUser.primaryEmail.toLowerCase()
+ const { userId } = await setupUser({ ...createUser(), email })
+ const request = await setupRequest({ code: githubUser.code })
+ const response = await loader({ request, params: PARAMS, context: {} })
+
+ expect(response).toHaveRedirect('/')
+
+ await expect(response).toSendToast(
+ expect.objectContaining({
+ type: 'message',
+ description: expect.stringContaining(githubUser.profile.login),
+ }),
+ )
+
+ const connection = await prisma.connection.findFirst({
+ select: { id: true },
+ where: {
+ userId: userId,
+ providerId: githubUser.profile.id.toString(),
+ },
+ })
+ expect(
+ connection,
+ 'the connection was not created in the database',
+ ).toBeTruthy()
+
+ await expect(response).toHaveSessionForUser(userId)
+})
+
+test('gives an error if the account is already connected to another user', async () => {
+ const githubUser = await insertGitHubUser()
+ await prisma.user.create({
+ data: {
+ ...createUser(),
+ connections: {
+ create: {
+ providerName: GITHUB_PROVIDER_NAME,
+ providerId: githubUser.profile.id.toString(),
+ },
+ },
+ },
+ })
+ const session = await setupUser()
+ const request = await setupRequest({
+ sessionId: session.id,
+ code: githubUser.code,
+ })
+ const response = await loader({ request, params: PARAMS, context: {} })
+ expect(response).toHaveRedirect('/settings/profile/connections')
+ await expect(response).toSendToast(
+ expect.objectContaining({
+ title: 'Already Connected',
+ description: expect.stringContaining(
+ 'already connected to another account',
+ ),
+ }),
+ )
+})
+
+test('if a user is not logged in, but the connection exists, make a session', async () => {
+ const githubUser = await insertGitHubUser()
+ const { userId } = await setupUser()
+ await prisma.connection.create({
+ data: {
+ providerName: GITHUB_PROVIDER_NAME,
+ providerId: githubUser.profile.id.toString(),
+ userId,
+ },
+ })
+ const request = await setupRequest({ code: githubUser.code })
+ const response = await loader({ request, params: PARAMS, context: {} })
+ expect(response).toHaveRedirect('/')
+ await expect(response).toHaveSessionForUser(userId)
+})
+
+test('if a user is not logged in, but the connection exists and they have enabled 2FA, send them to verify their 2FA and do not make a session', async () => {
+ const githubUser = await insertGitHubUser()
+ const { userId } = await setupUser()
+ await prisma.connection.create({
+ data: {
+ providerName: GITHUB_PROVIDER_NAME,
+ providerId: githubUser.profile.id.toString(),
+ userId,
+ },
+ })
+ const { otp: _otp, ...config } = generateTOTP()
+ await prisma.verification.create({
+ data: {
+ type: twoFAVerificationType,
+ target: userId,
+ ...config,
+ },
+ })
+ const request = await setupRequest({ code: githubUser.code })
+ const response = await loader({ request, params: PARAMS, context: {} })
+ const searchParams = new URLSearchParams({
+ type: twoFAVerificationType,
+ target: userId,
+ redirectTo: '/',
+ })
+ expect(response).toHaveRedirect(`/verify?${searchParams}`)
+})
+
+async function setupRequest({
+ sessionId,
+ code = faker.string.uuid(),
+}: { sessionId?: string; code?: string } = {}) {
+ const url = new URL(ROUTE_PATH, BASE_URL)
+ const state = faker.string.uuid()
+ url.searchParams.set('state', state)
+ url.searchParams.set('code', code)
+ const connectionSession = await connectionSessionStorage.getSession()
+ connectionSession.set('oauth2:state', state)
+ const authSession = await authSessionStorage.getSession()
+ if (sessionId) authSession.set(sessionKey, sessionId)
+ const setSessionCookieHeader =
+ await authSessionStorage.commitSession(authSession)
+ const setConnectionSessionCookieHeader =
+ await connectionSessionStorage.commitSession(connectionSession)
+ const request = new Request(url.toString(), {
+ method: 'GET',
+ headers: {
+ cookie: [
+ convertSetCookieToCookie(setConnectionSessionCookieHeader),
+ convertSetCookieToCookie(setSessionCookieHeader),
+ ].join('; '),
+ },
+ })
+ return request
+}
+
+async function setupUser(userData = createUser()) {
+ const session = await prisma.session.create({
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ user: {
+ create: {
+ ...userData,
+ },
+ },
+ },
+ select: {
+ id: true,
+ userId: true,
+ },
+ })
+
+ return session
+}
diff --git a/app/routes/_auth+/auth.$provider.callback.ts b/app/routes/_auth+/auth.$provider.callback.ts
new file mode 100644
index 0000000..2d7a730
--- /dev/null
+++ b/app/routes/_auth+/auth.$provider.callback.ts
@@ -0,0 +1,188 @@
+import { redirect, type LoaderFunctionArgs } from '@remix-run/node'
+import {
+ authenticator,
+ getSessionExpirationDate,
+ getUserId,
+} from '#app/utils/auth.server.ts'
+import { ProviderNameSchema, providerLabels } from '#app/utils/connections.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { ensurePrimary } from '#app/utils/litefs.server.ts'
+import { combineHeaders } from '#app/utils/misc.tsx'
+import {
+ normalizeEmail,
+ normalizeUsername,
+} from '#app/utils/providers/provider.ts'
+import {
+ destroyRedirectToHeader,
+ getRedirectCookieValue,
+} from '#app/utils/redirect-cookie.server.ts'
+import {
+ createToastHeaders,
+ redirectWithToast,
+} from '#app/utils/toast.server.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { handleNewSession } from './login.server.ts'
+import { onboardingEmailSessionKey } from './onboarding.tsx'
+import { prefilledProfileKey, providerIdKey } from './onboarding_.$provider.tsx'
+
+const destroyRedirectTo = { 'set-cookie': destroyRedirectToHeader }
+
+export async function loader({ request, params }: LoaderFunctionArgs) {
+ // this loader performs mutations, so we need to make sure we're on the
+ // primary instance to avoid writing to a read-only replica
+ await ensurePrimary()
+
+ const providerName = ProviderNameSchema.parse(params.provider)
+ const redirectTo = getRedirectCookieValue(request)
+ const label = providerLabels[providerName]
+
+ const authResult = await authenticator
+ .authenticate(providerName, request, { throwOnError: true })
+ .then(
+ (data) => ({ success: true, data }) as const,
+ (error) => ({ success: false, error }) as const,
+ )
+
+ if (!authResult.success) {
+ console.error(authResult.error)
+ throw await redirectWithToast(
+ '/login',
+ {
+ title: 'Auth Failed',
+ description: `There was an error authenticating with ${label}.`,
+ type: 'error',
+ },
+ { headers: destroyRedirectTo },
+ )
+ }
+
+ const { data: profile } = authResult
+
+ const existingConnection = await prisma.connection.findUnique({
+ select: { userId: true },
+ where: {
+ providerName_providerId: { providerName, providerId: profile.id },
+ },
+ })
+
+ const userId = await getUserId(request)
+
+ if (existingConnection && userId) {
+ if (existingConnection.userId === userId) {
+ return redirectWithToast(
+ '/settings/profile/connections',
+ {
+ title: 'Already Connected',
+ description: `Your "${profile.username}" ${label} account is already connected.`,
+ },
+ { headers: destroyRedirectTo },
+ )
+ } else {
+ return redirectWithToast(
+ '/settings/profile/connections',
+ {
+ title: 'Already Connected',
+ description: `The "${profile.username}" ${label} account is already connected to another account.`,
+ },
+ { headers: destroyRedirectTo },
+ )
+ }
+ }
+
+ // If we're already logged in, then link the account
+ if (userId) {
+ await prisma.connection.create({
+ data: {
+ providerName,
+ providerId: profile.id,
+ userId,
+ },
+ })
+ return redirectWithToast(
+ '/settings/profile/connections',
+ {
+ title: 'Connected',
+ type: 'success',
+ description: `Your "${profile.username}" ${label} account has been connected.`,
+ },
+ { headers: destroyRedirectTo },
+ )
+ }
+
+ // Connection exists already? Make a new session
+ if (existingConnection) {
+ return makeSession({ request, userId: existingConnection.userId })
+ }
+
+ // if the email matches a user in the db, then link the account and
+ // make a new session
+ const user = await prisma.user.findUnique({
+ select: { id: true },
+ where: { email: profile.email.toLowerCase() },
+ })
+ if (user) {
+ await prisma.connection.create({
+ data: {
+ providerName,
+ providerId: profile.id,
+ userId: user.id,
+ },
+ })
+ return makeSession(
+ { request, userId: user.id },
+ {
+ headers: await createToastHeaders({
+ title: 'Connected',
+ description: `Your "${profile.username}" ${label} account has been connected.`,
+ }),
+ },
+ )
+ }
+
+ // this is a new user, so let's get them onboarded
+ const verifySession = await verifySessionStorage.getSession()
+ verifySession.set(onboardingEmailSessionKey, profile.email)
+ verifySession.set(prefilledProfileKey, {
+ ...profile,
+ email: normalizeEmail(profile.email),
+ username:
+ typeof profile.username === 'string'
+ ? normalizeUsername(profile.username)
+ : undefined,
+ })
+ verifySession.set(providerIdKey, profile.id)
+ const onboardingRedirect = [
+ `/onboarding/${providerName}`,
+ redirectTo ? new URLSearchParams({ redirectTo }) : null,
+ ]
+ .filter(Boolean)
+ .join('?')
+ return redirect(onboardingRedirect, {
+ headers: combineHeaders(
+ { 'set-cookie': await verifySessionStorage.commitSession(verifySession) },
+ destroyRedirectTo,
+ ),
+ })
+}
+
+async function makeSession(
+ {
+ request,
+ userId,
+ redirectTo,
+ }: { request: Request; userId: string; redirectTo?: string | null },
+ responseInit?: ResponseInit,
+) {
+ redirectTo ??= '/'
+ const session = await prisma.session.create({
+ select: { id: true, expirationDate: true, userId: true },
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ userId,
+ },
+ })
+ return handleNewSession(
+ { request, session, redirectTo, remember: true },
+ { headers: combineHeaders(responseInit?.headers, destroyRedirectTo) },
+ )
+}
diff --git a/app/routes/_auth+/auth.$provider.ts b/app/routes/_auth+/auth.$provider.ts
new file mode 100644
index 0000000..7231920
--- /dev/null
+++ b/app/routes/_auth+/auth.$provider.ts
@@ -0,0 +1,33 @@
+import { redirect, type ActionFunctionArgs } from '@remix-run/node'
+import { authenticator } from '#app/utils/auth.server.ts'
+import { handleMockAction } from '#app/utils/connections.server.ts'
+import { ProviderNameSchema } from '#app/utils/connections.tsx'
+import { getReferrerRoute } from '#app/utils/misc.tsx'
+import { getRedirectCookieHeader } from '#app/utils/redirect-cookie.server.ts'
+
+export async function loader() {
+ return redirect('/login')
+}
+
+export async function action({ request, params }: ActionFunctionArgs) {
+ const providerName = ProviderNameSchema.parse(params.provider)
+
+ try {
+ await handleMockAction(providerName, request)
+ return await authenticator.authenticate(providerName, request)
+ } catch (error: unknown) {
+ if (error instanceof Response) {
+ const formData = await request.formData()
+ const rawRedirectTo = formData.get('redirectTo')
+ const redirectTo =
+ typeof rawRedirectTo === 'string'
+ ? rawRedirectTo
+ : getReferrerRoute(request)
+ const redirectToCookie = getRedirectCookieHeader(redirectTo)
+ if (redirectToCookie) {
+ error.headers.append('set-cookie', redirectToCookie)
+ }
+ }
+ throw error
+ }
+}
diff --git a/app/routes/_auth+/forgot-password.tsx b/app/routes/_auth+/forgot-password.tsx
new file mode 100644
index 0000000..f863eeb
--- /dev/null
+++ b/app/routes/_auth+/forgot-password.tsx
@@ -0,0 +1,194 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import * as E from '@react-email/components'
+import {
+ json,
+ redirect,
+ type ActionFunctionArgs,
+ type MetaFunction,
+} from '@remix-run/node'
+import { Link, useFetcher } from '@remix-run/react'
+import { HoneypotInputs } from 'remix-utils/honeypot/react'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { sendEmail } from '#app/utils/email.server.ts'
+import { checkHoneypot } from '#app/utils/honeypot.server.ts'
+import { EmailSchema, UsernameSchema } from '#app/utils/user-validation.ts'
+import { prepareVerification } from './verify.server.ts'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+const ForgotPasswordSchema = z.object({
+ usernameOrEmail: z.union([EmailSchema, UsernameSchema]),
+})
+
+export async function action({ request }: ActionFunctionArgs) {
+ const formData = await request.formData()
+ checkHoneypot(formData)
+ const submission = await parseWithZod(formData, {
+ schema: ForgotPasswordSchema.superRefine(async (data, ctx) => {
+ const user = await prisma.user.findFirst({
+ where: {
+ OR: [
+ { email: data.usernameOrEmail },
+ { username: data.usernameOrEmail },
+ ],
+ },
+ select: { id: true },
+ })
+ if (!user) {
+ ctx.addIssue({
+ path: ['usernameOrEmail'],
+ code: z.ZodIssueCode.custom,
+ message: 'No user exists with this username or email',
+ })
+ return
+ }
+ }),
+ async: true,
+ })
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+ const { usernameOrEmail } = submission.value
+
+ const user = await prisma.user.findFirstOrThrow({
+ where: { OR: [{ email: usernameOrEmail }, { username: usernameOrEmail }] },
+ select: { email: true, username: true },
+ })
+
+ const { verifyUrl, redirectTo, otp } = await prepareVerification({
+ period: 10 * 60,
+ request,
+ type: 'reset-password',
+ target: usernameOrEmail,
+ })
+
+ const response = await sendEmail({
+ to: user.email,
+ subject: `Epic Notes Password Reset`,
+ react: (
+
+ ),
+ })
+
+ if (response.status === 'success') {
+ return redirect(redirectTo.toString())
+ } else {
+ return json(
+ { result: submission.reply({ formErrors: [response.error.message] }) },
+ { status: 500 },
+ )
+ }
+}
+
+function ForgotPasswordEmail({
+ onboardingUrl,
+ otp,
+}: {
+ onboardingUrl: string
+ otp: string
+}) {
+ return (
+
+
+
+ Epic Notes Password Reset
+
+
+
+ Here's your verification code: {otp}
+
+
+
+ Or click the link:
+
+ {onboardingUrl}
+
+
+ )
+}
+
+export const meta: MetaFunction = () => {
+ return [{ title: 'Password Recovery for Epic Notes' }]
+}
+
+export default function ForgotPasswordRoute() {
+ const forgotPassword = useFetcher()
+
+ const [form, fields] = useForm({
+ id: 'forgot-password-form',
+ constraint: getZodConstraint(ForgotPasswordSchema),
+ lastResult: forgotPassword.data?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: ForgotPasswordSchema })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+
+
+
Forgot Password
+
+ No worries, we'll send you reset instructions.
+
+
+
+
+
+
+
+
+
+
+
+
+ Recover password
+
+
+
+
+ Back to Login
+
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return
+}
diff --git a/app/routes/_auth+/login.server.ts b/app/routes/_auth+/login.server.ts
new file mode 100644
index 0000000..4d4249a
--- /dev/null
+++ b/app/routes/_auth+/login.server.ts
@@ -0,0 +1,158 @@
+import { invariant } from '@epic-web/invariant'
+import { redirect } from '@remix-run/node'
+import { safeRedirect } from 'remix-utils/safe-redirect'
+import { twoFAVerificationType } from '#app/routes/settings+/profile.two-factor.tsx'
+import { getUserId, sessionKey } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { combineResponseInits } from '#app/utils/misc.tsx'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { getRedirectToUrl, type VerifyFunctionArgs } from './verify.server.ts'
+
+const verifiedTimeKey = 'verified-time'
+const unverifiedSessionIdKey = 'unverified-session-id'
+const rememberKey = 'remember'
+
+export async function handleNewSession(
+ {
+ request,
+ session,
+ redirectTo,
+ remember,
+ }: {
+ request: Request
+ session: { userId: string; id: string; expirationDate: Date }
+ redirectTo?: string
+ remember: boolean
+ },
+ responseInit?: ResponseInit,
+) {
+ const verification = await prisma.verification.findUnique({
+ select: { id: true },
+ where: {
+ target_type: { target: session.userId, type: twoFAVerificationType },
+ },
+ })
+ const userHasTwoFactor = Boolean(verification)
+
+ if (userHasTwoFactor) {
+ const verifySession = await verifySessionStorage.getSession()
+ verifySession.set(unverifiedSessionIdKey, session.id)
+ verifySession.set(rememberKey, remember)
+ const redirectUrl = getRedirectToUrl({
+ request,
+ type: twoFAVerificationType,
+ target: session.userId,
+ redirectTo,
+ })
+ return redirect(
+ `${redirectUrl.pathname}?${redirectUrl.searchParams}`,
+ combineResponseInits(
+ {
+ headers: {
+ 'set-cookie':
+ await verifySessionStorage.commitSession(verifySession),
+ },
+ },
+ responseInit,
+ ),
+ )
+ } else {
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ authSession.set(sessionKey, session.id)
+
+ return redirect(
+ safeRedirect(redirectTo),
+ combineResponseInits(
+ {
+ headers: {
+ 'set-cookie': await authSessionStorage.commitSession(authSession, {
+ expires: remember ? session.expirationDate : undefined,
+ }),
+ },
+ },
+ responseInit,
+ ),
+ )
+ }
+}
+
+export async function handleVerification({
+ request,
+ submission,
+}: VerifyFunctionArgs) {
+ invariant(
+ submission.status === 'success',
+ 'Submission should be successful by now',
+ )
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+
+ const remember = verifySession.get(rememberKey)
+ const { redirectTo } = submission.value
+ const headers = new Headers()
+ authSession.set(verifiedTimeKey, Date.now())
+
+ const unverifiedSessionId = verifySession.get(unverifiedSessionIdKey)
+ if (unverifiedSessionId) {
+ const session = await prisma.session.findUnique({
+ select: { expirationDate: true },
+ where: { id: unverifiedSessionId },
+ })
+ if (!session) {
+ throw await redirectWithToast('/login', {
+ type: 'error',
+ title: 'Invalid session',
+ description: 'Could not find session to verify. Please try again.',
+ })
+ }
+ authSession.set(sessionKey, unverifiedSessionId)
+
+ headers.append(
+ 'set-cookie',
+ await authSessionStorage.commitSession(authSession, {
+ expires: remember ? session.expirationDate : undefined,
+ }),
+ )
+ } else {
+ headers.append(
+ 'set-cookie',
+ await authSessionStorage.commitSession(authSession),
+ )
+ }
+
+ headers.append(
+ 'set-cookie',
+ await verifySessionStorage.destroySession(verifySession),
+ )
+
+ return redirect(safeRedirect(redirectTo), { headers })
+}
+
+export async function shouldRequestTwoFA(request: Request) {
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ if (verifySession.has(unverifiedSessionIdKey)) return true
+ const userId = await getUserId(request)
+ if (!userId) return false
+ // if it's over two hours since they last verified, we should request 2FA again
+ const userHasTwoFA = await prisma.verification.findUnique({
+ select: { id: true },
+ where: { target_type: { target: userId, type: twoFAVerificationType } },
+ })
+ if (!userHasTwoFA) return false
+ const verifiedTime = authSession.get(verifiedTimeKey) ?? new Date(0)
+ const twoHours = 1000 * 60 * 2
+ return Date.now() - verifiedTime > twoHours
+}
diff --git a/app/routes/_auth+/login.tsx b/app/routes/_auth+/login.tsx
new file mode 100644
index 0000000..e15d84b
--- /dev/null
+++ b/app/routes/_auth+/login.tsx
@@ -0,0 +1,210 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ type ActionFunctionArgs,
+ type LoaderFunctionArgs,
+ type MetaFunction,
+} from '@remix-run/node'
+import { Form, Link, useActionData, useSearchParams } from '@remix-run/react'
+import { HoneypotInputs } from 'remix-utils/honeypot/react'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
+import { Spacer } from '#app/components/spacer.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { login, requireAnonymous } from '#app/utils/auth.server.ts'
+import {
+ ProviderConnectionForm,
+ providerNames,
+} from '#app/utils/connections.tsx'
+import { checkHoneypot } from '#app/utils/honeypot.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { PasswordSchema, UsernameSchema } from '#app/utils/user-validation.ts'
+import { handleNewSession } from './login.server.ts'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+const LoginFormSchema = z.object({
+ username: UsernameSchema,
+ password: PasswordSchema,
+ redirectTo: z.string().optional(),
+ remember: z.boolean().optional(),
+})
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ await requireAnonymous(request)
+ return json({})
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ await requireAnonymous(request)
+ const formData = await request.formData()
+ checkHoneypot(formData)
+ const submission = await parseWithZod(formData, {
+ schema: (intent) =>
+ LoginFormSchema.transform(async (data, ctx) => {
+ if (intent !== null) return { ...data, session: null }
+
+ const session = await login(data)
+ if (!session) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: 'Invalid username or password',
+ })
+ return z.NEVER
+ }
+
+ return { ...data, session }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success' || !submission.value.session) {
+ return json(
+ { result: submission.reply({ hideFields: ['password'] }) },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { session, remember, redirectTo } = submission.value
+
+ return handleNewSession({
+ request,
+ session,
+ remember: remember ?? false,
+ redirectTo,
+ })
+}
+
+export default function LoginPage() {
+ const actionData = useActionData()
+ const isPending = useIsPending()
+ const [searchParams] = useSearchParams()
+ const redirectTo = searchParams.get('redirectTo')
+
+ const [form, fields] = useForm({
+ id: 'login-form',
+ constraint: getZodConstraint(LoginFormSchema),
+ defaultValue: { redirectTo },
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: LoginFormSchema })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+
+
+
Welcome back!
+
+ Please enter your details.
+
+
+
+
+
+
+
+
+ {providerNames.map((providerName) => (
+
+
+
+ ))}
+
+
+ New here?
+
+ Create an account
+
+
+
+
+
+
+ )
+}
+
+export const meta: MetaFunction = () => {
+ return [{ title: 'Login to Epic Notes' }]
+}
+
+export function ErrorBoundary() {
+ return
+}
diff --git a/app/routes/_auth+/logout.tsx b/app/routes/_auth+/logout.tsx
new file mode 100644
index 0000000..876757e
--- /dev/null
+++ b/app/routes/_auth+/logout.tsx
@@ -0,0 +1,10 @@
+import { redirect, type ActionFunctionArgs } from '@remix-run/node'
+import { logout } from '#app/utils/auth.server.ts'
+
+export async function loader() {
+ return redirect('/')
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ return logout({ request })
+}
diff --git a/app/routes/_auth+/onboarding.server.ts b/app/routes/_auth+/onboarding.server.ts
new file mode 100644
index 0000000..826a72a
--- /dev/null
+++ b/app/routes/_auth+/onboarding.server.ts
@@ -0,0 +1,19 @@
+import { invariant } from '@epic-web/invariant'
+import { redirect } from '@remix-run/node'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { onboardingEmailSessionKey } from './onboarding.tsx'
+import { type VerifyFunctionArgs } from './verify.server.ts'
+
+export async function handleVerification({ submission }: VerifyFunctionArgs) {
+ invariant(
+ submission.status === 'success',
+ 'Submission should be successful by now',
+ )
+ const verifySession = await verifySessionStorage.getSession()
+ verifySession.set(onboardingEmailSessionKey, submission.value.target)
+ return redirect('/onboarding', {
+ headers: {
+ 'set-cookie': await verifySessionStorage.commitSession(verifySession),
+ },
+ })
+}
diff --git a/app/routes/_auth+/onboarding.tsx b/app/routes/_auth+/onboarding.tsx
new file mode 100644
index 0000000..0424761
--- /dev/null
+++ b/app/routes/_auth+/onboarding.tsx
@@ -0,0 +1,242 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import {
+ json,
+ redirect,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+ type MetaFunction,
+} from '@remix-run/node'
+import {
+ Form,
+ useActionData,
+ useLoaderData,
+ useSearchParams,
+} from '@remix-run/react'
+import { HoneypotInputs } from 'remix-utils/honeypot/react'
+import { safeRedirect } from 'remix-utils/safe-redirect'
+import { z } from 'zod'
+import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
+import { Spacer } from '#app/components/spacer.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireAnonymous, sessionKey, signup } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { checkHoneypot } from '#app/utils/honeypot.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import {
+ NameSchema,
+ PasswordAndConfirmPasswordSchema,
+ UsernameSchema,
+} from '#app/utils/user-validation.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+
+export const onboardingEmailSessionKey = 'onboardingEmail'
+
+const SignupFormSchema = z
+ .object({
+ username: UsernameSchema,
+ name: NameSchema,
+ agreeToTermsOfServiceAndPrivacyPolicy: z.boolean({
+ required_error:
+ 'You must agree to the terms of service and privacy policy',
+ }),
+ remember: z.boolean().optional(),
+ redirectTo: z.string().optional(),
+ })
+ .and(PasswordAndConfirmPasswordSchema)
+
+async function requireOnboardingEmail(request: Request) {
+ await requireAnonymous(request)
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const email = verifySession.get(onboardingEmailSessionKey)
+ if (typeof email !== 'string' || !email) {
+ throw redirect('/signup')
+ }
+ return email
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const email = await requireOnboardingEmail(request)
+ return json({ email })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const email = await requireOnboardingEmail(request)
+ const formData = await request.formData()
+ checkHoneypot(formData)
+ const submission = await parseWithZod(formData, {
+ schema: (intent) =>
+ SignupFormSchema.superRefine(async (data, ctx) => {
+ const existingUser = await prisma.user.findUnique({
+ where: { username: data.username },
+ select: { id: true },
+ })
+ if (existingUser) {
+ ctx.addIssue({
+ path: ['username'],
+ code: z.ZodIssueCode.custom,
+ message: 'A user already exists with this username',
+ })
+ return
+ }
+ }).transform(async (data) => {
+ if (intent !== null) return { ...data, session: null }
+
+ const session = await signup({ ...data, email })
+ return { ...data, session }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success' || !submission.value.session) {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { session, remember, redirectTo } = submission.value
+
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ authSession.set(sessionKey, session.id)
+ const verifySession = await verifySessionStorage.getSession()
+ const headers = new Headers()
+ headers.append(
+ 'set-cookie',
+ await authSessionStorage.commitSession(authSession, {
+ expires: remember ? session.expirationDate : undefined,
+ }),
+ )
+ headers.append(
+ 'set-cookie',
+ await verifySessionStorage.destroySession(verifySession),
+ )
+
+ return redirectWithToast(
+ safeRedirect(redirectTo),
+ { title: 'Welcome', description: 'Thanks for signing up!' },
+ { headers },
+ )
+}
+
+export const meta: MetaFunction = () => {
+ return [{ title: 'Setup Epic Notes Account' }]
+}
+
+export default function OnboardingRoute() {
+ const data = useLoaderData()
+ const actionData = useActionData()
+ const isPending = useIsPending()
+ const [searchParams] = useSearchParams()
+ const redirectTo = searchParams.get('redirectTo')
+
+ const [form, fields] = useForm({
+ id: 'onboarding-form',
+ constraint: getZodConstraint(SignupFormSchema),
+ defaultValue: { redirectTo },
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: SignupFormSchema })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+
+
+
Welcome aboard {data.email}!
+
+ Please enter your details.
+
+
+
+
+
+
+ )
+}
diff --git a/app/routes/_auth+/onboarding_.$provider.server.ts b/app/routes/_auth+/onboarding_.$provider.server.ts
new file mode 100644
index 0000000..826a72a
--- /dev/null
+++ b/app/routes/_auth+/onboarding_.$provider.server.ts
@@ -0,0 +1,19 @@
+import { invariant } from '@epic-web/invariant'
+import { redirect } from '@remix-run/node'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { onboardingEmailSessionKey } from './onboarding.tsx'
+import { type VerifyFunctionArgs } from './verify.server.ts'
+
+export async function handleVerification({ submission }: VerifyFunctionArgs) {
+ invariant(
+ submission.status === 'success',
+ 'Submission should be successful by now',
+ )
+ const verifySession = await verifySessionStorage.getSession()
+ verifySession.set(onboardingEmailSessionKey, submission.value.target)
+ return redirect('/onboarding', {
+ headers: {
+ 'set-cookie': await verifySessionStorage.commitSession(verifySession),
+ },
+ })
+}
diff --git a/app/routes/_auth+/onboarding_.$provider.tsx b/app/routes/_auth+/onboarding_.$provider.tsx
new file mode 100644
index 0000000..9cbdc51
--- /dev/null
+++ b/app/routes/_auth+/onboarding_.$provider.tsx
@@ -0,0 +1,285 @@
+import {
+ getFormProps,
+ getInputProps,
+ useForm,
+ type SubmissionResult,
+} from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import {
+ redirect,
+ json,
+ type ActionFunctionArgs,
+ type LoaderFunctionArgs,
+ type MetaFunction,
+} from '@remix-run/node'
+import {
+ type Params,
+ Form,
+ useActionData,
+ useLoaderData,
+ useSearchParams,
+} from '@remix-run/react'
+import { safeRedirect } from 'remix-utils/safe-redirect'
+import { z } from 'zod'
+import { CheckboxField, ErrorList, Field } from '#app/components/forms.tsx'
+import { Spacer } from '#app/components/spacer.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import {
+ authenticator,
+ sessionKey,
+ signupWithConnection,
+ requireAnonymous,
+} from '#app/utils/auth.server.ts'
+import { connectionSessionStorage } from '#app/utils/connections.server'
+import { ProviderNameSchema } from '#app/utils/connections.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { NameSchema, UsernameSchema } from '#app/utils/user-validation.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { onboardingEmailSessionKey } from './onboarding'
+
+export const providerIdKey = 'providerId'
+export const prefilledProfileKey = 'prefilledProfile'
+
+const SignupFormSchema = z.object({
+ imageUrl: z.string().optional(),
+ username: UsernameSchema,
+ name: NameSchema,
+ agreeToTermsOfServiceAndPrivacyPolicy: z.boolean({
+ required_error: 'You must agree to the terms of service and privacy policy',
+ }),
+ remember: z.boolean().optional(),
+ redirectTo: z.string().optional(),
+})
+
+async function requireData({
+ request,
+ params,
+}: {
+ request: Request
+ params: Params
+}) {
+ await requireAnonymous(request)
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const email = verifySession.get(onboardingEmailSessionKey)
+ const providerId = verifySession.get(providerIdKey)
+ const result = z
+ .object({
+ email: z.string(),
+ providerName: ProviderNameSchema,
+ providerId: z.string(),
+ })
+ .safeParse({ email, providerName: params.provider, providerId })
+ if (result.success) {
+ return result.data
+ } else {
+ console.error(result.error)
+ throw redirect('/signup')
+ }
+}
+
+export async function loader({ request, params }: LoaderFunctionArgs) {
+ const { email } = await requireData({ request, params })
+ const connectionSession = await connectionSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const prefilledProfile = verifySession.get(prefilledProfileKey)
+
+ const formError = connectionSession.get(authenticator.sessionErrorKey)
+ const hasError = typeof formError === 'string'
+
+ return json({
+ email,
+ status: 'idle',
+ submission: {
+ status: hasError ? 'error' : undefined,
+ initialValue: prefilledProfile ?? {},
+ error: { '': hasError ? [formError] : [] },
+ } as SubmissionResult,
+ })
+}
+
+export async function action({ request, params }: ActionFunctionArgs) {
+ const { email, providerId, providerName } = await requireData({
+ request,
+ params,
+ })
+ const formData = await request.formData()
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+
+ const submission = await parseWithZod(formData, {
+ schema: SignupFormSchema.superRefine(async (data, ctx) => {
+ const existingUser = await prisma.user.findUnique({
+ where: { username: data.username },
+ select: { id: true },
+ })
+ if (existingUser) {
+ ctx.addIssue({
+ path: ['username'],
+ code: z.ZodIssueCode.custom,
+ message: 'A user already exists with this username',
+ })
+ return
+ }
+ }).transform(async (data) => {
+ const session = await signupWithConnection({
+ ...data,
+ email,
+ providerId,
+ providerName,
+ })
+ return { ...data, session }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { session, remember, redirectTo } = submission.value
+
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ authSession.set(sessionKey, session.id)
+ const headers = new Headers()
+ headers.append(
+ 'set-cookie',
+ await authSessionStorage.commitSession(authSession, {
+ expires: remember ? session.expirationDate : undefined,
+ }),
+ )
+ headers.append(
+ 'set-cookie',
+ await verifySessionStorage.destroySession(verifySession),
+ )
+
+ return redirectWithToast(
+ safeRedirect(redirectTo),
+ { title: 'Welcome', description: 'Thanks for signing up!' },
+ { headers },
+ )
+}
+
+export const meta: MetaFunction = () => {
+ return [{ title: 'Setup Epic Notes Account' }]
+}
+
+export default function OnboardingProviderRoute() {
+ const data = useLoaderData()
+ const actionData = useActionData()
+ const isPending = useIsPending()
+ const [searchParams] = useSearchParams()
+ const redirectTo = searchParams.get('redirectTo')
+
+ const [form, fields] = useForm({
+ id: 'onboarding-provider-form',
+ constraint: getZodConstraint(SignupFormSchema),
+ lastResult: actionData?.result ?? data.submission,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: SignupFormSchema })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+
+
+
Welcome aboard {data.email}!
+
+ Please enter your details.
+
+
+
+
+
+
+ )
+}
diff --git a/app/routes/_auth+/reset-password.server.ts b/app/routes/_auth+/reset-password.server.ts
new file mode 100644
index 0000000..1c25b4d
--- /dev/null
+++ b/app/routes/_auth+/reset-password.server.ts
@@ -0,0 +1,34 @@
+import { invariant } from '@epic-web/invariant'
+import { json, redirect } from '@remix-run/node'
+import { prisma } from '#app/utils/db.server.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { resetPasswordUsernameSessionKey } from './reset-password.tsx'
+import { type VerifyFunctionArgs } from './verify.server.ts'
+
+export async function handleVerification({ submission }: VerifyFunctionArgs) {
+ invariant(
+ submission.status === 'success',
+ 'Submission should be successful by now',
+ )
+ const target = submission.value.target
+ const user = await prisma.user.findFirst({
+ where: { OR: [{ email: target }, { username: target }] },
+ select: { email: true, username: true },
+ })
+ // we don't want to say the user is not found if the email is not found
+ // because that would allow an attacker to check if an email is registered
+ if (!user) {
+ return json(
+ { result: submission.reply({ fieldErrors: { code: ['Invalid code'] } }) },
+ { status: 400 },
+ )
+ }
+
+ const verifySession = await verifySessionStorage.getSession()
+ verifySession.set(resetPasswordUsernameSessionKey, user.username)
+ return redirect('/reset-password', {
+ headers: {
+ 'set-cookie': await verifySessionStorage.commitSession(verifySession),
+ },
+ })
+}
diff --git a/app/routes/_auth+/reset-password.tsx b/app/routes/_auth+/reset-password.tsx
new file mode 100644
index 0000000..38e4763
--- /dev/null
+++ b/app/routes/_auth+/reset-password.tsx
@@ -0,0 +1,141 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type ActionFunctionArgs,
+ type LoaderFunctionArgs,
+ type MetaFunction,
+} from '@remix-run/node'
+import { Form, useActionData, useLoaderData } from '@remix-run/react'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireAnonymous, resetUserPassword } from '#app/utils/auth.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { PasswordAndConfirmPasswordSchema } from '#app/utils/user-validation.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+export const resetPasswordUsernameSessionKey = 'resetPasswordUsername'
+
+const ResetPasswordSchema = PasswordAndConfirmPasswordSchema
+
+async function requireResetPasswordUsername(request: Request) {
+ await requireAnonymous(request)
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const resetPasswordUsername = verifySession.get(
+ resetPasswordUsernameSessionKey,
+ )
+ if (typeof resetPasswordUsername !== 'string' || !resetPasswordUsername) {
+ throw redirect('/login')
+ }
+ return resetPasswordUsername
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const resetPasswordUsername = await requireResetPasswordUsername(request)
+ return json({ resetPasswordUsername })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const resetPasswordUsername = await requireResetPasswordUsername(request)
+ const formData = await request.formData()
+ const submission = parseWithZod(formData, {
+ schema: ResetPasswordSchema,
+ })
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+ const { password } = submission.value
+
+ await resetUserPassword({ username: resetPasswordUsername, password })
+ const verifySession = await verifySessionStorage.getSession()
+ return redirect('/login', {
+ headers: {
+ 'set-cookie': await verifySessionStorage.destroySession(verifySession),
+ },
+ })
+}
+
+export const meta: MetaFunction = () => {
+ return [{ title: 'Reset Password | Epic Notes' }]
+}
+
+export default function ResetPasswordPage() {
+ const data = useLoaderData()
+ const actionData = useActionData()
+ const isPending = useIsPending()
+
+ const [form, fields] = useForm({
+ id: 'reset-password',
+ constraint: getZodConstraint(ResetPasswordSchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: ResetPasswordSchema })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+
+
Password Reset
+
+ Hi, {data.resetPasswordUsername}. No worries. It happens all the time.
+
+
+
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return
+}
diff --git a/app/routes/_auth+/signup.tsx b/app/routes/_auth+/signup.tsx
new file mode 100644
index 0000000..6d475a3
--- /dev/null
+++ b/app/routes/_auth+/signup.tsx
@@ -0,0 +1,191 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import * as E from '@react-email/components'
+import {
+ json,
+ redirect,
+ type ActionFunctionArgs,
+ type MetaFunction,
+} from '@remix-run/node'
+import { Form, useActionData, useSearchParams } from '@remix-run/react'
+import { HoneypotInputs } from 'remix-utils/honeypot/react'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import {
+ ProviderConnectionForm,
+ providerNames,
+} from '#app/utils/connections.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { sendEmail } from '#app/utils/email.server.ts'
+import { checkHoneypot } from '#app/utils/honeypot.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { EmailSchema } from '#app/utils/user-validation.ts'
+import { prepareVerification } from './verify.server.ts'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+const SignupSchema = z.object({
+ email: EmailSchema,
+})
+
+export async function action({ request }: ActionFunctionArgs) {
+ const formData = await request.formData()
+
+ checkHoneypot(formData)
+
+ const submission = await parseWithZod(formData, {
+ schema: SignupSchema.superRefine(async (data, ctx) => {
+ const existingUser = await prisma.user.findUnique({
+ where: { email: data.email },
+ select: { id: true },
+ })
+ if (existingUser) {
+ ctx.addIssue({
+ path: ['email'],
+ code: z.ZodIssueCode.custom,
+ message: 'A user already exists with this email',
+ })
+ return
+ }
+ }),
+ async: true,
+ })
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+ const { email } = submission.value
+ const { verifyUrl, redirectTo, otp } = await prepareVerification({
+ period: 10 * 60,
+ request,
+ type: 'onboarding',
+ target: email,
+ })
+
+ const response = await sendEmail({
+ to: email,
+ subject: `Welcome to Epic Notes!`,
+ react: ,
+ })
+
+ if (response.status === 'success') {
+ return redirect(redirectTo.toString())
+ } else {
+ return json(
+ {
+ result: submission.reply({ formErrors: [response.error.message] }),
+ },
+ {
+ status: 500,
+ },
+ )
+ }
+}
+
+export function SignupEmail({
+ onboardingUrl,
+ otp,
+}: {
+ onboardingUrl: string
+ otp: string
+}) {
+ return (
+
+
+
+ Welcome to Epic Notes!
+
+
+
+ Here's your verification code: {otp}
+
+
+
+ Or click the link to get started:
+
+ {onboardingUrl}
+
+
+ )
+}
+
+export const meta: MetaFunction = () => {
+ return [{ title: 'Sign Up | Epic Notes' }]
+}
+
+export default function SignupRoute() {
+ const actionData = useActionData()
+ const isPending = useIsPending()
+ const [searchParams] = useSearchParams()
+ const redirectTo = searchParams.get('redirectTo')
+
+ const [form, fields] = useForm({
+ id: 'signup-form',
+ constraint: getZodConstraint(SignupSchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ const result = parseWithZod(formData, { schema: SignupSchema })
+ return result
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+
+
Let's start your journey!
+
+ Please enter your email.
+
+
+
+
+
+ {providerNames.map((providerName) => (
+
+
+
+ ))}
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return
+}
diff --git a/app/routes/_auth+/verify.server.ts b/app/routes/_auth+/verify.server.ts
new file mode 100644
index 0000000..dccd55a
--- /dev/null
+++ b/app/routes/_auth+/verify.server.ts
@@ -0,0 +1,200 @@
+import { type Submission } from '@conform-to/react'
+import { parseWithZod } from '@conform-to/zod'
+import { json } from '@remix-run/node'
+import { z } from 'zod'
+import { handleVerification as handleChangeEmailVerification } from '#app/routes/settings+/profile.change-email.server.tsx'
+import { twoFAVerificationType } from '#app/routes/settings+/profile.two-factor.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { getDomainUrl } from '#app/utils/misc.tsx'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { generateTOTP, verifyTOTP } from '#app/utils/totp.server.ts'
+import { type twoFAVerifyVerificationType } from '../settings+/profile.two-factor.verify.tsx'
+import {
+ handleVerification as handleLoginTwoFactorVerification,
+ shouldRequestTwoFA,
+} from './login.server.ts'
+import { handleVerification as handleOnboardingVerification } from './onboarding.server.ts'
+import { handleVerification as handleResetPasswordVerification } from './reset-password.server.ts'
+import {
+ VerifySchema,
+ codeQueryParam,
+ redirectToQueryParam,
+ targetQueryParam,
+ typeQueryParam,
+ type VerificationTypes,
+} from './verify.tsx'
+
+export type VerifyFunctionArgs = {
+ request: Request
+ submission: Submission<
+ z.input,
+ string[],
+ z.output
+ >
+ body: FormData | URLSearchParams
+}
+
+export function getRedirectToUrl({
+ request,
+ type,
+ target,
+ redirectTo,
+}: {
+ request: Request
+ type: VerificationTypes
+ target: string
+ redirectTo?: string
+}) {
+ const redirectToUrl = new URL(`${getDomainUrl(request)}/verify`)
+ redirectToUrl.searchParams.set(typeQueryParam, type)
+ redirectToUrl.searchParams.set(targetQueryParam, target)
+ if (redirectTo) {
+ redirectToUrl.searchParams.set(redirectToQueryParam, redirectTo)
+ }
+ return redirectToUrl
+}
+
+export async function requireRecentVerification(request: Request) {
+ const userId = await requireUserId(request)
+ const shouldReverify = await shouldRequestTwoFA(request)
+ if (shouldReverify) {
+ const reqUrl = new URL(request.url)
+ const redirectUrl = getRedirectToUrl({
+ request,
+ target: userId,
+ type: twoFAVerificationType,
+ redirectTo: reqUrl.pathname + reqUrl.search,
+ })
+ throw await redirectWithToast(redirectUrl.toString(), {
+ title: 'Please Reverify',
+ description: 'Please reverify your account before proceeding',
+ })
+ }
+}
+
+export async function prepareVerification({
+ period,
+ request,
+ type,
+ target,
+}: {
+ period: number
+ request: Request
+ type: VerificationTypes
+ target: string
+}) {
+ const verifyUrl = getRedirectToUrl({ request, type, target })
+ const redirectTo = new URL(verifyUrl.toString())
+
+ const { otp, ...verificationConfig } = generateTOTP({
+ algorithm: 'SHA256',
+ // Leaving off 0, O, and I on purpose to avoid confusing users.
+ charSet: 'ABCDEFGHJKLMNPQRSTUVWXYZ123456789',
+ period,
+ })
+ const verificationData = {
+ type,
+ target,
+ ...verificationConfig,
+ expiresAt: new Date(Date.now() + verificationConfig.period * 1000),
+ }
+ await prisma.verification.upsert({
+ where: { target_type: { target, type } },
+ create: verificationData,
+ update: verificationData,
+ })
+
+ // add the otp to the url we'll email the user.
+ verifyUrl.searchParams.set(codeQueryParam, otp)
+
+ return { otp, redirectTo, verifyUrl }
+}
+
+export async function isCodeValid({
+ code,
+ type,
+ target,
+}: {
+ code: string
+ type: VerificationTypes | typeof twoFAVerifyVerificationType
+ target: string
+}) {
+ const verification = await prisma.verification.findUnique({
+ where: {
+ target_type: { target, type },
+ OR: [{ expiresAt: { gt: new Date() } }, { expiresAt: null }],
+ },
+ select: { algorithm: true, secret: true, period: true, charSet: true },
+ })
+ if (!verification) return false
+ const result = verifyTOTP({
+ otp: code,
+ ...verification,
+ })
+ if (!result) return false
+
+ return true
+}
+
+export async function validateRequest(
+ request: Request,
+ body: URLSearchParams | FormData,
+) {
+ const submission = await parseWithZod(body, {
+ schema: VerifySchema.superRefine(async (data, ctx) => {
+ const codeIsValid = await isCodeValid({
+ code: data[codeQueryParam],
+ type: data[typeQueryParam],
+ target: data[targetQueryParam],
+ })
+ if (!codeIsValid) {
+ ctx.addIssue({
+ path: ['code'],
+ code: z.ZodIssueCode.custom,
+ message: `Invalid code`,
+ })
+ return
+ }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { value: submissionValue } = submission
+
+ async function deleteVerification() {
+ await prisma.verification.delete({
+ where: {
+ target_type: {
+ type: submissionValue[typeQueryParam],
+ target: submissionValue[targetQueryParam],
+ },
+ },
+ })
+ }
+
+ switch (submissionValue[typeQueryParam]) {
+ case 'reset-password': {
+ await deleteVerification()
+ return handleResetPasswordVerification({ request, body, submission })
+ }
+ case 'onboarding': {
+ await deleteVerification()
+ return handleOnboardingVerification({ request, body, submission })
+ }
+ case 'change-email': {
+ await deleteVerification()
+ return handleChangeEmailVerification({ request, body, submission })
+ }
+ case '2fa': {
+ return handleLoginTwoFactorVerification({ request, body, submission })
+ }
+ }
+}
diff --git a/app/routes/_auth+/verify.tsx b/app/routes/_auth+/verify.tsx
new file mode 100644
index 0000000..0cd8fb0
--- /dev/null
+++ b/app/routes/_auth+/verify.tsx
@@ -0,0 +1,145 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import { type ActionFunctionArgs } from '@remix-run/node'
+import { Form, useActionData, useSearchParams } from '@remix-run/react'
+import { HoneypotInputs } from 'remix-utils/honeypot/react'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { ErrorList, OTPField } from '#app/components/forms.tsx'
+import { Spacer } from '#app/components/spacer.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { checkHoneypot } from '#app/utils/honeypot.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { validateRequest } from './verify.server.ts'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+export const codeQueryParam = 'code'
+export const targetQueryParam = 'target'
+export const typeQueryParam = 'type'
+export const redirectToQueryParam = 'redirectTo'
+const types = ['onboarding', 'reset-password', 'change-email', '2fa'] as const
+const VerificationTypeSchema = z.enum(types)
+export type VerificationTypes = z.infer
+
+export const VerifySchema = z.object({
+ [codeQueryParam]: z.string().min(6).max(6),
+ [typeQueryParam]: VerificationTypeSchema,
+ [targetQueryParam]: z.string(),
+ [redirectToQueryParam]: z.string().optional(),
+})
+
+export async function action({ request }: ActionFunctionArgs) {
+ const formData = await request.formData()
+ checkHoneypot(formData)
+ return validateRequest(request, formData)
+}
+
+export default function VerifyRoute() {
+ const [searchParams] = useSearchParams()
+ const isPending = useIsPending()
+ const actionData = useActionData()
+ const parseWithZoddType = VerificationTypeSchema.safeParse(
+ searchParams.get(typeQueryParam),
+ )
+ const type = parseWithZoddType.success ? parseWithZoddType.data : null
+
+ const checkEmail = (
+ <>
+ Check your email
+
+ We've sent you a code to verify your email address.
+
+ >
+ )
+
+ const headings: Record = {
+ onboarding: checkEmail,
+ 'reset-password': checkEmail,
+ 'change-email': checkEmail,
+ '2fa': (
+ <>
+ Check your 2FA app
+
+ Please enter your 2FA code to verify your identity.
+
+ >
+ ),
+ }
+
+ const [form, fields] = useForm({
+ id: 'verify-form',
+ constraint: getZodConstraint(VerifySchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: VerifySchema })
+ },
+ defaultValue: {
+ code: searchParams.get(codeQueryParam),
+ type: type,
+ target: searchParams.get(targetQueryParam),
+ redirectTo: searchParams.get(redirectToQueryParam),
+ },
+ })
+
+ return (
+
+
+ {type ? headings[type] : 'Invalid Verification Type'}
+
+
+
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return
+}
diff --git a/app/routes/_marketing+/about.tsx b/app/routes/_marketing+/about.tsx
new file mode 100644
index 0000000..55ef96d
--- /dev/null
+++ b/app/routes/_marketing+/about.tsx
@@ -0,0 +1,3 @@
+export default function AboutRoute() {
+ return About page
+}
diff --git a/app/routes/_marketing+/index.tsx b/app/routes/_marketing+/index.tsx
new file mode 100644
index 0000000..0598ecb
--- /dev/null
+++ b/app/routes/_marketing+/index.tsx
@@ -0,0 +1,41 @@
+import { type MetaFunction } from '@remix-run/node'
+import { Link } from '@remix-run/react'
+
+export const meta: MetaFunction = () => [{ title: 'Epic Notes' }]
+
+export default function Index() {
+ return (
+
+
+
+ Faxdienst
+
+
+
+ Kunden-
+
+ dienst
+
+
+
+ Liste
+
+
+
+ )
+}
diff --git a/app/routes/_marketing+/logos/docker.svg b/app/routes/_marketing+/logos/docker.svg
new file mode 100644
index 0000000..b39ecde
--- /dev/null
+++ b/app/routes/_marketing+/logos/docker.svg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/eslint.svg b/app/routes/_marketing+/logos/eslint.svg
new file mode 100644
index 0000000..dd535a8
--- /dev/null
+++ b/app/routes/_marketing+/logos/eslint.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/faker.svg b/app/routes/_marketing+/logos/faker.svg
new file mode 100644
index 0000000..e290a83
--- /dev/null
+++ b/app/routes/_marketing+/logos/faker.svg
@@ -0,0 +1,736 @@
+
+
+
+ Layer 1
+
+ Group
+
+ Group
+
+ Shape 272
+
+
+
+
+
+
+
+
+
+ Shape 273
+
+
+
+
+
+
+
+
+
+ Shape 274
+
+
+
+
+
+
+
+
+
+ Shape 275
+
+
+
+
+
+
+
+
+
+ Shape 276
+
+
+
+
+
+
+
+
+
+ Shape 277
+
+
+
+
+
+
+
+
+
+ Shape 278
+
+
+
+
+
+
+
+
+
+ Shape 279
+
+
+
+
+
+
+
+
+
+ Shape 280
+
+
+
+
+
+
+
+
+
+ Shape 281
+
+
+
+
+
+
+
+
+
+ Shape 282
+
+
+
+
+
+
+
+
+
+ Shape 283
+
+
+
+
+
+
+
+
+
+ Shape 284
+
+
+
+
+
+
+
+
+
+ Shape 285
+
+
+
+
+
+
+
+
+
+ Shape 286
+
+
+
+
+
+
+
+
+
+ Shape 287
+
+
+
+
+
+
+
+
+
+ Shape 288
+
+
+
+
+
+
+
+
+
+ Shape 289
+
+
+
+
+
+
+
+
+
+ Shape 290
+
+
+
+
+
+
+
+
+
+ Shape 291
+
+
+
+
+
+
+
+
+
+ Shape 292
+
+
+
+
+
+
+
+
+
+ Shape 293
+
+
+
+
+
+
+
+
+
+ Shape 294
+
+
+
+
+
+
+
+
+
+ Shape 295
+
+
+
+
+
+
+
+
+
+ Shape 296
+
+
+
+
+
+
+
+
+
+ Shape 297
+
+
+
+
+
+
+
+
+
+ Shape 298
+
+
+
+
+
+
+
+
+
+ Shape 299
+
+
+
+
+
+
+
+
+
+ Shape 300
+
+
+
+
+
+
+
+
+
+ Shape 301
+
+
+
+
+
+
+
+
+
+ Shape 302
+
+
+
+
+
+
+
+
+
+ Shape 303
+
+
+
+
+
+
+
+
+
+ Shape 304
+
+
+
+
+
+
+
+
+
+ Shape 305
+
+
+
+
+
+
+
+
+
+ Shape 306
+
+
+
+
+
+
+
+
+
+ Shape 307
+
+
+
+
+
+
+
+
+
+ Shape 308
+
+
+
+
+
+
+
+
+
+ Shape 309
+
+
+
+
+
+
+
+
+
+ Shape 310
+
+
+
+
+
+
+
+
+
+ Shape 311
+
+
+
+
+
+
+
+
+
+ Shape 312
+
+
+
+
+
+
+
+
+
+ Shape 313
+
+
+
+
+
+
+
+
+
+ Shape 314
+
+
+
+
+
+
+
+
+
+ Shape 315
+
+
+
+
+
+
+
+
+
+ Shape 316
+
+
+
+
+
+
+
+
+
+ Shape 317
+
+
+
+
+
+
+
+
+
+ Shape 318
+
+
+
+
+
+
+
+
+
+ Shape 319
+
+
+
+
+
+
+
+
+
+ Shape 320
+
+
+
+
+
+
+
+
+
+ Shape 321
+
+
+
+
+
+
+
+
+
+ Shape 322
+
+
+
+
+
+
+
+
+
+ Shape 323
+
+
+
+
+
+
+
+
+
+ Shape 324
+
+
+
+
+
+
+
+
+
+ Shape 325
+
+
+
+
+
+
+
+
+
+ Shape 326
+
+
+
+
+
+
+
+
+
+ Shape 327
+
+
+
+
+
+
+
+
+
+ Shape 328
+
+
+
+
+
+
+
+
+
+ Shape 329
+
+
+
+
+
+
+
+
+
+ Shape 330
+
+
+
+
+
+
+
+
+
+ Shape 331
+
+
+
+
+
+
+
+
+
+ Shape 332
+
+
+
+
+
+
+
+
+
+ Shape 333
+
+
+
+
+
+
+
+
+
+ Shape 334
+
+
+
+
+
+
+
+
+
+ Shape 335
+
+
+
+
+
+
+
+
+
+ Shape 336
+
+
+
+
+
+
+
+
+
+ Shape 337
+
+
+
+
+
+
+
+
+
+ Shape 338
+
+
+
+
+
+
+
+
+
+
+ Shape 339
+
+
+
+
+
+
+
+
+
+
+ Shape 340
+
+
+
+
+
+
+
+
+
+
+ Shape 341
+
+
+
+
+
+
+
+
+
+
+ Shape 342
+
+
+
+
+
+
+
+
+
+ Shape 343
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/fly.svg b/app/routes/_marketing+/logos/fly.svg
new file mode 100644
index 0000000..9dbf3c7
--- /dev/null
+++ b/app/routes/_marketing+/logos/fly.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/github.svg b/app/routes/_marketing+/logos/github.svg
new file mode 100644
index 0000000..37fa923
--- /dev/null
+++ b/app/routes/_marketing+/logos/github.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/logos.ts b/app/routes/_marketing+/logos/logos.ts
new file mode 100644
index 0000000..7d77e8a
--- /dev/null
+++ b/app/routes/_marketing+/logos/logos.ts
@@ -0,0 +1,173 @@
+import docker from './docker.svg'
+import eslint from './eslint.svg'
+import fakerJS from './faker.svg'
+import fly from './fly.svg'
+import github from './github.svg'
+import msw from './msw.svg'
+import playwright from './playwright.svg'
+import prettier from './prettier.svg'
+import prisma from './prisma.svg'
+import radixUI from './radix.svg'
+import reactEmail from './react-email.svg'
+import remix from './remix.svg'
+import resend from './resend.svg'
+import sentry from './sentry.svg'
+import shadcnUI from './shadcn-ui.svg'
+import sqlite from './sqlite.svg'
+import tailwind from './tailwind.svg'
+import testingLibrary from './testing-library.png'
+import typescript from './typescript.svg'
+import vitest from './vitest.svg'
+import zod from './zod.svg'
+
+export { default as stars } from './stars.jpg'
+
+export const logos = [
+ {
+ src: remix,
+ alt: 'Remix',
+ href: 'https://remix.run',
+ column: 1,
+ row: 1,
+ },
+ {
+ src: fly,
+ alt: 'Fly.io',
+ href: 'https://fly.io',
+ column: 1,
+ row: 2,
+ },
+ {
+ src: sqlite,
+ alt: 'SQLite',
+ href: 'https://sqlite.org',
+ column: 1,
+ row: 3,
+ },
+ {
+ src: prisma,
+ alt: 'Prisma',
+ href: 'https://prisma.io',
+ column: 2,
+ row: 2,
+ },
+ {
+ src: zod,
+ alt: 'Zod',
+ href: 'https://zod.dev/',
+ column: 2,
+ row: 3,
+ },
+ {
+ src: github,
+ alt: 'GitHub',
+ href: 'https://github.com',
+ column: 2,
+ row: 4,
+ },
+ {
+ src: resend,
+ alt: 'Resend',
+ href: 'https://resend.com',
+ column: 2,
+ row: 5,
+ },
+ {
+ src: reactEmail,
+ alt: 'React Email',
+ href: 'https://react.email',
+ column: 2,
+ row: 6,
+ },
+ {
+ src: tailwind,
+ alt: 'Tailwind CSS',
+ href: 'https://tailwindcss.com',
+ column: 3,
+ row: 3,
+ },
+ {
+ src: radixUI,
+ alt: 'Radix UI',
+ href: 'https://www.radix-ui.com/',
+ column: 3,
+ row: 4,
+ },
+ {
+ src: shadcnUI,
+ alt: 'shadcn/ui',
+ href: 'https://ui.shadcn.com/',
+ column: 3,
+ row: 5,
+ },
+ {
+ src: playwright,
+ alt: 'Playwright',
+ href: 'https://playwright.dev/',
+ column: 4,
+ row: 1,
+ },
+ {
+ src: msw,
+ alt: 'MSW',
+ href: 'https://mswjs.io',
+ column: 4,
+ row: 2,
+ },
+ {
+ src: fakerJS,
+ alt: 'Faker.js',
+ href: 'https://fakerjs.dev/',
+ column: 4,
+ row: 3,
+ },
+ {
+ src: vitest,
+ alt: 'Vitest',
+ href: 'https://vitest.dev',
+ column: 4,
+ row: 4,
+ },
+ {
+ src: testingLibrary,
+ alt: 'Testing Library',
+ href: 'https://testing-library.com',
+ column: 4,
+ row: 5,
+ },
+ {
+ src: docker,
+ alt: 'Docker',
+ href: 'https://www.docker.com',
+ column: 4,
+ row: 6,
+ },
+ {
+ src: typescript,
+ alt: 'TypeScript',
+ href: 'https://typescriptlang.org',
+ column: 5,
+ row: 2,
+ },
+ {
+ src: prettier,
+ alt: 'Prettier',
+ href: 'https://prettier.io',
+ column: 5,
+ row: 3,
+ },
+ {
+ src: eslint,
+ alt: 'ESLint',
+ href: 'https://eslint.org',
+ column: 5,
+ row: 4,
+ },
+ {
+ src: sentry,
+ alt: 'Sentry',
+ href: 'https://sentry.io',
+ column: 5,
+ row: 5,
+ },
+]
diff --git a/app/routes/_marketing+/logos/msw.svg b/app/routes/_marketing+/logos/msw.svg
new file mode 100644
index 0000000..f5de6fb
--- /dev/null
+++ b/app/routes/_marketing+/logos/msw.svg
@@ -0,0 +1,13 @@
+
+
+ LOGO
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/playwright.svg b/app/routes/_marketing+/logos/playwright.svg
new file mode 100644
index 0000000..7b3ca7d
--- /dev/null
+++ b/app/routes/_marketing+/logos/playwright.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/prettier.svg b/app/routes/_marketing+/logos/prettier.svg
new file mode 100644
index 0000000..f4d0b66
--- /dev/null
+++ b/app/routes/_marketing+/logos/prettier.svg
@@ -0,0 +1,76 @@
+
+
+
+ prettier-icon-dark
+ Created with sketchtool.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/prisma.svg b/app/routes/_marketing+/logos/prisma.svg
new file mode 100644
index 0000000..17a3886
--- /dev/null
+++ b/app/routes/_marketing+/logos/prisma.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/radix.svg b/app/routes/_marketing+/logos/radix.svg
new file mode 100644
index 0000000..a748299
--- /dev/null
+++ b/app/routes/_marketing+/logos/radix.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/react-email.svg b/app/routes/_marketing+/logos/react-email.svg
new file mode 100644
index 0000000..51a2698
--- /dev/null
+++ b/app/routes/_marketing+/logos/react-email.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/remix.svg b/app/routes/_marketing+/logos/remix.svg
new file mode 100644
index 0000000..2f4a5ab
--- /dev/null
+++ b/app/routes/_marketing+/logos/remix.svg
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/resend.svg b/app/routes/_marketing+/logos/resend.svg
new file mode 100644
index 0000000..1227dc5
--- /dev/null
+++ b/app/routes/_marketing+/logos/resend.svg
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/sentry.svg b/app/routes/_marketing+/logos/sentry.svg
new file mode 100644
index 0000000..3ebb3bb
--- /dev/null
+++ b/app/routes/_marketing+/logos/sentry.svg
@@ -0,0 +1,6 @@
+
+
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/shadcn-ui.svg b/app/routes/_marketing+/logos/shadcn-ui.svg
new file mode 100644
index 0000000..2780f68
--- /dev/null
+++ b/app/routes/_marketing+/logos/shadcn-ui.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/sqlite.svg b/app/routes/_marketing+/logos/sqlite.svg
new file mode 100644
index 0000000..424e0ab
--- /dev/null
+++ b/app/routes/_marketing+/logos/sqlite.svg
@@ -0,0 +1,67 @@
+
+
+
+SQLite image/svg+xml SQLite
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/stars.jpg b/app/routes/_marketing+/logos/stars.jpg
new file mode 100644
index 0000000..c725b8a
Binary files /dev/null and b/app/routes/_marketing+/logos/stars.jpg differ
diff --git a/app/routes/_marketing+/logos/tailwind.svg b/app/routes/_marketing+/logos/tailwind.svg
new file mode 100644
index 0000000..6a9ab49
--- /dev/null
+++ b/app/routes/_marketing+/logos/tailwind.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/routes/_marketing+/logos/testing-library.png b/app/routes/_marketing+/logos/testing-library.png
new file mode 100644
index 0000000..6febb2a
Binary files /dev/null and b/app/routes/_marketing+/logos/testing-library.png differ
diff --git a/app/routes/_marketing+/logos/typescript.svg b/app/routes/_marketing+/logos/typescript.svg
new file mode 100644
index 0000000..339da0b
--- /dev/null
+++ b/app/routes/_marketing+/logos/typescript.svg
@@ -0,0 +1,6 @@
+
+
+TypeScript logo
+
+
+
diff --git a/app/routes/_marketing+/logos/vitest.svg b/app/routes/_marketing+/logos/vitest.svg
new file mode 100644
index 0000000..fd9daaf
--- /dev/null
+++ b/app/routes/_marketing+/logos/vitest.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/routes/_marketing+/logos/zod.svg b/app/routes/_marketing+/logos/zod.svg
new file mode 100644
index 0000000..0595f51
--- /dev/null
+++ b/app/routes/_marketing+/logos/zod.svg
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/routes/_marketing+/privacy.tsx b/app/routes/_marketing+/privacy.tsx
new file mode 100644
index 0000000..b6d6530
--- /dev/null
+++ b/app/routes/_marketing+/privacy.tsx
@@ -0,0 +1,3 @@
+export default function PrivacyRoute() {
+ return Privacy
+}
diff --git a/app/routes/_marketing+/support.tsx b/app/routes/_marketing+/support.tsx
new file mode 100644
index 0000000..ec9a242
--- /dev/null
+++ b/app/routes/_marketing+/support.tsx
@@ -0,0 +1,3 @@
+export default function SupportRoute() {
+ return Support
+}
diff --git a/app/routes/_marketing+/tailwind-preset.ts b/app/routes/_marketing+/tailwind-preset.ts
new file mode 100644
index 0000000..f155649
--- /dev/null
+++ b/app/routes/_marketing+/tailwind-preset.ts
@@ -0,0 +1,27 @@
+import { type Config } from 'tailwindcss'
+
+export const marketingPreset = {
+ theme: {
+ extend: {
+ keyframes: {
+ 'roll-reveal': {
+ from: { transform: 'rotate(12deg) scale(0)', opacity: '0' },
+ to: { transform: 'rotate(0deg) scale(1)', opacity: '1' },
+ },
+ 'slide-left': {
+ from: { transform: 'translateX(20px)', opacity: '0' },
+ to: { transform: 'translateX(0px)', opacity: '1' },
+ },
+ 'slide-top': {
+ from: { transform: 'translateY(20px)', opacity: '0' },
+ to: { transform: 'translateY(0px)', opacity: '1' },
+ },
+ },
+ animation: {
+ 'roll-reveal': 'roll-reveal 0.4s cubic-bezier(.22,1.28,.54,.99)',
+ 'slide-left': 'slide-left 0.3s ease-out',
+ 'slide-top': 'slide-top 0.3s ease-out',
+ },
+ },
+ },
+} satisfies Omit
diff --git a/app/routes/_marketing+/tos.tsx b/app/routes/_marketing+/tos.tsx
new file mode 100644
index 0000000..998f867
--- /dev/null
+++ b/app/routes/_marketing+/tos.tsx
@@ -0,0 +1,3 @@
+export default function TermsOfServiceRoute() {
+ return Terms of service
+}
diff --git a/app/routes/_publicare+/dashboard_kunde.tsx b/app/routes/_publicare+/dashboard_kunde.tsx
new file mode 100644
index 0000000..98e7023
--- /dev/null
+++ b/app/routes/_publicare+/dashboard_kunde.tsx
@@ -0,0 +1,22 @@
+import {Link} from "@remix-run/react";
+
+export default function NeueBestellungPage() {
+
+ return (
+
+
+
Neue Bestellung
+
+
+
Neuer Patient
+
+
+
Liste Bestellungen
+
+
+
Verwaltung
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/dashboard_privatkunde.tsx b/app/routes/_publicare+/dashboard_privatkunde.tsx
new file mode 100644
index 0000000..7967f1c
--- /dev/null
+++ b/app/routes/_publicare+/dashboard_privatkunde.tsx
@@ -0,0 +1,16 @@
+import {Link} from "@remix-run/react";
+
+export default function NeueBestellungPage() {
+
+ return (
+
+
+
Neue Bestellung
+
+
+
Liste Bestellungen
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/exampleData.tsx b/app/routes/_publicare+/exampleData.tsx
new file mode 100644
index 0000000..243fde2
--- /dev/null
+++ b/app/routes/_publicare+/exampleData.tsx
@@ -0,0 +1,106 @@
+import { subDays } from 'date-fns'
+
+export const exampleData = [
+ {
+ sender: 'max.mustermann@example.com',
+ source: 'Email',
+ title: 'Bestellung',
+ message: 'Vielen Dank fĂźr Ihre Nachricht',
+ received: subDays(new Date(), 10),
+ number: 1,
+ of: 2,
+ bereich: '',
+ bearbeiter: '',
+ status: 'Faxdienst',
+ kunde: '',
+ document: {
+ type: 'image',
+ src: '/demodata/e-rezept.png',
+ },
+ },
+ {
+ sender: 'max.mustermann@example.com',
+ source: 'Email',
+ title: 'Bestellung',
+ message: 'Vielen Dank fĂźr Ihre Nachricht',
+ received: subDays(new Date(), 10),
+ number: 2,
+ of: 2,
+ bereich: '',
+ bearbeiter: '',
+ status: 'Faxdienst',
+ kunde: '',
+ document: {
+ type: 'pdf',
+ src: '/demodata/prescription.pdf',
+ },
+ },
+ {
+ sender: 'max.mustermann@example.com',
+ source: 'Email',
+ title: 'Verortnungsschein Nachlieferung',
+ message: '',
+ number: 1,
+ of: 1,
+ bereich: 'StoMa',
+ bearbeiter: '',
+ status: 'Kundendienst',
+ kunde: '1234567',
+ received: subDays(new Date(), 9),
+ document: {
+ type: 'image',
+ src: '/demodata/rezept.png',
+ },
+ },
+ {
+ sender: '',
+ source: 'Webform',
+ title: '',
+ message: '',
+ number: 1,
+ of: 1,
+ bereich: 'Wunderversorgung',
+ bearbeiter: 'EK',
+ status: 'Kundendienst',
+ kunde: 'Neuanlage',
+ received: subDays(new Date(), 7),
+ document: {
+ type: 'image',
+ src: '/demodata/verordnung.jpg',
+ },
+ },
+ {
+ sender: '+43 66666 6666',
+ source: 'Fax',
+ title: 'New fax from ++437677620763550',
+ message: 'You got a new fax: ....',
+ number: 1,
+ of: 1,
+ bereich: 'Wundversorgung',
+ bearbeiter: 'SUFU',
+ status: 'Erledigt',
+ kunde: '1234567',
+ received: subDays(new Date(), 6),
+ document: {
+ type: 'image',
+ src: '/demodata/Verordnung_muster.webp',
+ },
+ },
+ {
+ sender: '',
+ source: 'Webform',
+ number: 1,
+ of: 1,
+ title: '',
+ message: '',
+ bereich: 'Sonstige',
+ bearbeiter: 'CM',
+ status: 'Erledigt',
+ kunde: '234567',
+ received: subDays(new Date(), 4),
+ document: {
+ type: 'image',
+ src: '/demodata/Verordnung_muster.webp',
+ },
+ },
+]
diff --git a/app/routes/_publicare+/faxdienst.tsx b/app/routes/_publicare+/faxdienst.tsx
new file mode 100644
index 0000000..e72b615
--- /dev/null
+++ b/app/routes/_publicare+/faxdienst.tsx
@@ -0,0 +1,185 @@
+import { useState } from 'react'
+import { Button } from '#app/components/ui/button.tsx'
+import { Field, TextareaField } from '#app/components/forms.tsx'
+import { Badge } from '#app/components/ui/badge.tsx'
+import { clsx } from 'clsx'
+
+import { exampleData } from './exampleData.tsx'
+
+export default function NeueBestellungPage() {
+ const assignableTo = [
+ 'AR',
+ 'AWO',
+ 'BL',
+ 'CH',
+ 'CM',
+ 'EK',
+ 'JU',
+ 'MAS',
+ 'NR',
+ 'SIST',
+ 'SKA',
+ 'SP',
+ 'STS',
+ 'SUFU',
+ 'SUL',
+ ]
+
+ const [currentIndex, setCurrentIndex] = useState(0)
+ const [bereich, setBereich] = useState('')
+ const [assignedTo, setAssignedTo] = useState('')
+ const [customer, setCustomer] = useState('Neuanlage')
+ const currentItem =
+ currentIndex <= exampleData.length ? exampleData[currentIndex] : null
+
+ function OptionButton(props: {
+ value: string
+ currentValue: string
+ setFn: (newValue: string) => void
+ }) {
+ const { value, currentValue, setFn } = props
+ return (
+ {
+ setFn(value)
+ }}
+ >
+ {value}
+
+ )
+ }
+
+ return (
+
+
+ {!currentItem && (
+
+ Keine weiteren Anfragen zu bearbeiten
+
+ )}
+ {currentItem && (
+
+
+ {currentItem.document?.type === 'pdf' && (
+
+ )}
+ {currentItem.document?.type === 'image' && (
+
+ )}
+ {!currentItem.document &&
Kein Dokument angehängt }
+
+
+
+
Nachricht
+ Quelle:
{currentItem.source}
+
+ Sender: {currentItem.sender || ''}
+
+ Titel: {currentItem.title || ''}
+
+ Dokument: {currentItem.number} / {currentItem.of}
+
+ Originalnachricht
+
+
+ Erhalten am: {currentItem.received.toLocaleDateString()}
+
+
+
+
Faxdienst
+
+
+
Kundendienst-MA:
+
+ {assignableTo.map((short) => (
+
+ ))}
+
+
+
+
+
Kunde:
+
+
+
+ KndNr.:
+
+
+
+
+
+
LĂśschen
+
+
{
+ setCurrentIndex((oldIndex) => oldIndex + 1)
+ }}
+ >
+ Ăberspringen
+
+
{
+ setCurrentIndex((oldIndex) => oldIndex + 1)
+ }}
+ >
+ Speichern & Nächste
+
+
+
+
+
+ )}
+
+
+ )
+}
diff --git a/app/routes/_publicare+/kundendienst.tsx b/app/routes/_publicare+/kundendienst.tsx
new file mode 100644
index 0000000..9ae04ff
--- /dev/null
+++ b/app/routes/_publicare+/kundendienst.tsx
@@ -0,0 +1,224 @@
+import { useState } from 'react'
+import { Button } from '#app/components/ui/button.tsx'
+import { Field, TextareaField } from '#app/components/forms.tsx'
+import { Badge } from '#app/components/ui/badge.tsx'
+import { clsx } from 'clsx'
+import { exampleData } from './exampleData.tsx'
+
+export default function NeueBestellungPage() {
+ const assignableTo = [
+ 'AR',
+ 'AWO',
+ 'BL',
+ 'CH',
+ 'CM',
+ 'EK',
+ 'JU',
+ 'MAS',
+ 'NR',
+ 'SIST',
+ 'SKA',
+ 'SP',
+ 'STS',
+ 'SUFU',
+ 'SUL',
+ ]
+
+ const bereiche = ['StoMa', 'Wundversorgung', 'Sonstige']
+ const customers = ['Neuanlage', 'Bestandskunde']
+ const kundenNr = ['1234567', '2345678', '3456789']
+
+ function getRandomNumber(max: number) {
+ return Math.floor(max * Math.random())
+ }
+
+ const [currentIndex, setCurrentIndex] = useState(0)
+ const [bereich, setBereich] = useState(
+ bereiche[getRandomNumber(bereiche.length)] || '',
+ )
+ const [assignedTo, setAssignedTo] = useState(
+ assignableTo[getRandomNumber(assignableTo.length)] || '',
+ )
+ const [customer, setCustomer] = useState(
+ customers[getRandomNumber(customers.length)] || '',
+ )
+ const currentItem =
+ currentIndex <= exampleData.length ? exampleData[currentIndex] : null
+
+ function showNextEntry() {
+ setCustomer(customers[getRandomNumber(customers.length)] || '')
+ setAssignedTo(assignableTo[getRandomNumber(assignableTo.length)] || '')
+ setBereich(bereiche[getRandomNumber(bereiche.length)] || '')
+ setCurrentIndex((oldIndex) => oldIndex + 1)
+ }
+
+ function OptionButton(props: {
+ value: string
+ currentValue: string
+ setFn: (newValue: string) => void
+ }) {
+ const { value, currentValue, setFn } = props
+ return (
+ {
+ setFn(value)
+ }}
+ >
+ {value}
+
+ )
+ }
+
+ return (
+
+
+ {!currentItem && (
+
+ Keine weiteren Anfragen zu bearbeiten
+
+ )}
+ {currentItem && (
+
+
+ {currentItem.document?.type === 'pdf' && (
+
+ )}
+ {currentItem.document?.type === 'image' && (
+
+ )}
+ {!currentItem.document &&
Kein Dokument angehängt }
+
+
+
+
Nachricht
+ Quelle:
{currentItem.source}
+
+ Sender: {currentItem.sender || ''}
+
+ Titel: {currentItem.title || ''}
+
+ Dokument: {currentItem.number} / {currentItem.of}
+
+ Originalnachricht
+
+
+ Erhalten am: {currentItem.received.toLocaleDateString()}
+
+
+
+
Kundendienst:
+
+
+
Kundendienst-MA:
+
+ {assignableTo.map((short) => (
+
+ ))}
+
+
+
+
+
Kunde:
+
+
+
+ KndNr.:
+
+
+
+
+
+
LĂśschen
+
+
{}}>
+ PDF drucken
+
+
{
+ showNextEntry()
+ }}
+ >
+ Ăberspringen
+
+
{
+ showNextEntry()
+ }}
+ >
+ Speichern
+
+
{
+ showNextEntry()
+ }}
+ >
+ Erledigt
+
+
+
+
+
+ )}
+
+
+ )
+}
diff --git a/app/routes/_publicare+/liste.tsx b/app/routes/_publicare+/liste.tsx
new file mode 100644
index 0000000..1a8d63a
--- /dev/null
+++ b/app/routes/_publicare+/liste.tsx
@@ -0,0 +1,88 @@
+import {
+ Table,
+ TableRow,
+ TableBody,
+ TableHeader,
+ TableHead,
+ TableCell,
+} from '../../components/ui/table.tsx'
+import { exampleData } from '#app/routes/_publicare+/exampleData.tsx'
+import { Badge } from '#app/components/ui/badge.tsx'
+import { Field } from '#app/components/forms.tsx'
+import { useNavigate } from 'react-router'
+
+export default function () {
+ const navigate = useNavigate()
+ return (
+
+
+
+
+ Erhalten
+ Quelle
+ Bereich
+ Bearbeiter
+ Kunde
+ Status
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {exampleData.map((data) => (
+ {
+ navigate('/kundendienst')
+ }}
+ >
+ {data.received.toLocaleString()}
+
+ {data.source}
+
+ {data.bereich}
+ {data.bearbeiter}
+ {data.kunde}
+ {data.status}
+
+ ))}
+
+
+
+ )
+}
diff --git a/app/routes/_publicare+/liste_bestellungen_kunde.tsx b/app/routes/_publicare+/liste_bestellungen_kunde.tsx
new file mode 100644
index 0000000..d809884
--- /dev/null
+++ b/app/routes/_publicare+/liste_bestellungen_kunde.tsx
@@ -0,0 +1,52 @@
+import {useNavigate} from "react-router";
+import {Table, TableBody, TableHead, TableRow, TableCell, TableHeader, TableCaption} from "#app/components/ui/table.tsx"
+import {Badge} from "#app/components/ui/badge.tsx";
+import {Icon} from "#app/components/ui/icon.tsx";
+import {VisuallyHidden} from "@radix-ui/react-visually-hidden";
+
+export default function() {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Bestellungen
+
+
+
+ A list of your recent orders.
+
+
+
+
+ Datum
+ Bestellnr.:
+ Verordnung
+ Status
+
+
+
+
+ 01.10.2024 10:00
+ #1234
+ fehlt
+ In Bearbeitung
+
+
+ 03.10.2024 10:00
+ #1333
+
+ Abrechnung Krankekasse
+
+
+ 05.10.2024 10:00
+ #2345
+
+ Erledigt
+
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/liste_bestellungen_privatkunde.tsx b/app/routes/_publicare+/liste_bestellungen_privatkunde.tsx
new file mode 100644
index 0000000..d809884
--- /dev/null
+++ b/app/routes/_publicare+/liste_bestellungen_privatkunde.tsx
@@ -0,0 +1,52 @@
+import {useNavigate} from "react-router";
+import {Table, TableBody, TableHead, TableRow, TableCell, TableHeader, TableCaption} from "#app/components/ui/table.tsx"
+import {Badge} from "#app/components/ui/badge.tsx";
+import {Icon} from "#app/components/ui/icon.tsx";
+import {VisuallyHidden} from "@radix-ui/react-visually-hidden";
+
+export default function() {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Bestellungen
+
+
+
+ A list of your recent orders.
+
+
+
+
+ Datum
+ Bestellnr.:
+ Verordnung
+ Status
+
+
+
+
+ 01.10.2024 10:00
+ #1234
+ fehlt
+ In Bearbeitung
+
+
+ 03.10.2024 10:00
+ #1333
+
+ Abrechnung Krankekasse
+
+
+ 05.10.2024 10:00
+ #2345
+
+ Erledigt
+
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/neue_bestellung.tsx b/app/routes/_publicare+/neue_bestellung.tsx
new file mode 100644
index 0000000..69b26cc
--- /dev/null
+++ b/app/routes/_publicare+/neue_bestellung.tsx
@@ -0,0 +1,27 @@
+import {useNavigate} from "react-router";
+
+export default function NeueBestellungPage() {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Neuer Patient
+
+
+
+ Name
+
+
+ Sozialversicherungsnr.
+
+
{
+ navigate('/dashboard_kunde')
+ }}>
+ Absenden
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/neuer_patient.tsx b/app/routes/_publicare+/neuer_patient.tsx
new file mode 100644
index 0000000..f03b33f
--- /dev/null
+++ b/app/routes/_publicare+/neuer_patient.tsx
@@ -0,0 +1,25 @@
+import {useNavigate} from "react-router";
+
+export default function NeueBestellungPage() {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Neue Bestellung
+
+
+
+ Patient auswählen
+
+
+ Verordnung
+
+
{navigate('/dashboard_kunde')}}>
+ Absenden
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/registrierung.tsx b/app/routes/_publicare+/registrierung.tsx
new file mode 100644
index 0000000..d353f0f
--- /dev/null
+++ b/app/routes/_publicare+/registrierung.tsx
@@ -0,0 +1,29 @@
+import {useNavigate} from "react-router";
+
+export default function() {
+
+ const navigate = useNavigate();
+
+
+ return (
+
+
+ Registrierung
+
+
+
+ Name
+
+
+ Email/Telefon
+
+
{
+ navigate('/registrierung_step_2')
+ }}>
+ Weiter
+
+
+
+ )
+ ;
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/registrierung_step_2.tsx b/app/routes/_publicare+/registrierung_step_2.tsx
new file mode 100644
index 0000000..ca34c79
--- /dev/null
+++ b/app/routes/_publicare+/registrierung_step_2.tsx
@@ -0,0 +1,25 @@
+import {Link} from "@remix-run/react";
+
+export default function() {
+
+ return (
+
+
+ Registrierung
+
+
+
+
+ Option 1: Ich bestelle fĂźr mich selbst bzw. einen AngehĂśrigen
+
+
+
+
+ Option 2: Ich bin Angestellter und bestelle stellvertretend fĂźr unsere Kunden
+
+
+
+
+ )
+ ;
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/registrierung_step_3_organisation.tsx b/app/routes/_publicare+/registrierung_step_3_organisation.tsx
new file mode 100644
index 0000000..4f5a184
--- /dev/null
+++ b/app/routes/_publicare+/registrierung_step_3_organisation.tsx
@@ -0,0 +1,28 @@
+import {useNavigate} from "react-router";
+import {Link} from "@remix-run/react";
+
+export default function () {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Organisation
+
+
+
+
+ Bestehende Organisation auswählen
+
+
+
oder
+
+
+ Neue Organisation anlegen
+
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/registrierung_step_3_privat.tsx b/app/routes/_publicare+/registrierung_step_3_privat.tsx
new file mode 100644
index 0000000..f2db501
--- /dev/null
+++ b/app/routes/_publicare+/registrierung_step_3_privat.tsx
@@ -0,0 +1,33 @@
+import {useNavigate} from "react-router";
+
+export default function () {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Daten eingeben
+
+
+
+ Name
+
+
+ Sozialversicherungsnr.
+
+
+ Hausarzt
+
+
+ Telefonnr.
+
+
{
+ navigate('/dashboard_kunde')
+ }}>
+ Registrierung abschlieĂen
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/registrierung_step_4_neue_organisation.tsx b/app/routes/_publicare+/registrierung_step_4_neue_organisation.tsx
new file mode 100644
index 0000000..97615e8
--- /dev/null
+++ b/app/routes/_publicare+/registrierung_step_4_neue_organisation.tsx
@@ -0,0 +1,36 @@
+import {useNavigate} from "react-router";
+
+export default function () {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Neues Unternehmen
+
+
+
+ Name
+
+
+ Adresse
+
+
+ PLZ/Ort
+
+
+ Telefonnr.
+
+
+ E-Mail
+
+
{
+ navigate('/dashboard_kunde')
+ }}>
+ Registrierung abschlieĂen
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/registrierung_step_4_zuordnung_organisation.tsx b/app/routes/_publicare+/registrierung_step_4_zuordnung_organisation.tsx
new file mode 100644
index 0000000..728380b
--- /dev/null
+++ b/app/routes/_publicare+/registrierung_step_4_zuordnung_organisation.tsx
@@ -0,0 +1,19 @@
+import {useNavigate} from "react-router";
+
+export default function () {
+
+ const navigate = useNavigate();
+ return (
+
+
+ Zuordnung Organisation
+
+
+
+ Wir haben den Administrator der Organisation verständigt. Sobald er ihre Teilnahme freigibt erhalten sie eine Benachrichtigung.
+
+
+
+ );
+
+}
\ No newline at end of file
diff --git a/app/routes/_publicare+/website.tsx b/app/routes/_publicare+/website.tsx
new file mode 100644
index 0000000..c91c344
--- /dev/null
+++ b/app/routes/_publicare+/website.tsx
@@ -0,0 +1,27 @@
+import {Link} from "@remix-run/react";
+
+export default function() {
+ return (
+
+
+
+
Schritt 1 â Rezept/Verordnungsschein besorgen
+
Damit wir sie mit Produkten beliefern dĂźrfen, benĂśtigen wir ein gĂźltiges Rezept bzw. einen gĂźltigen Verordnungsschein. Ihr behandelnder Arzt im Krankenhaus oder im niedergelassenen Bereich (Praktischer Arzt, Facharzt) stellt ein Rezept / einen Verordnungschein Ăźber die von ihnen benĂśtigten Hilfsmittel aus.
+
Hat ihre Krankenkasse eine Dauerverordnung genehmigt, so reicht ein Anruf, ein Fax oder eine Email an unseren Kundendienst, um eine Lieferung der von ihnen benĂśtigten Hilfsmittel zu veranlassen.
+
+
+
Schritt 2 â Zusendung des Rezeptes/Verordnungsscheines
+
+ Das Rezept oder den Verordnungschein bitte Ăźber unser Online-Formular, per Email (bestellung@publicare.at ), per Fax (07229 70560-60) oder per Post an uns senden.
+
+
+ Fßr ihre Bestellung reicht ein Fax oder Email des Rezeptes bzw. des Verordnungscheines aus. Fßr die Abrechnung mit den Krankenkassen benÜtigen wir allerdings zusätzlich das Original.
+
+
+ Ihrer Lieferung liegt standardmäĂig ein kostenloser RĂźckumschlag bei, in dem sie uns ihr Originalrezept portofrei zuschicken kĂśnnen. Bedenken sie bitte, dass die Zustellung eines Rezeptes/Verordnungscheines bis zu drei Werktagen dauern kann.
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/app/routes/_seo+/robots[.]txt.ts b/app/routes/_seo+/robots[.]txt.ts
new file mode 100644
index 0000000..94280a1
--- /dev/null
+++ b/app/routes/_seo+/robots[.]txt.ts
@@ -0,0 +1,9 @@
+import { generateRobotsTxt } from '@nasa-gcn/remix-seo'
+import { type LoaderFunctionArgs } from '@remix-run/node'
+import { getDomainUrl } from '#app/utils/misc.tsx'
+
+export function loader({ request }: LoaderFunctionArgs) {
+ return generateRobotsTxt([
+ { type: 'sitemap', value: `${getDomainUrl(request)}/sitemap.xml` },
+ ])
+}
diff --git a/app/routes/_seo+/sitemap[.]xml.ts b/app/routes/_seo+/sitemap[.]xml.ts
new file mode 100644
index 0000000..a3ebb26
--- /dev/null
+++ b/app/routes/_seo+/sitemap[.]xml.ts
@@ -0,0 +1,13 @@
+import { generateSitemap } from '@nasa-gcn/remix-seo'
+import { type ServerBuild, type LoaderFunctionArgs } from '@remix-run/node'
+import { getDomainUrl } from '#app/utils/misc.tsx'
+
+export async function loader({ request, context }: LoaderFunctionArgs) {
+ const serverBuild = (await context.serverBuild) as { build: ServerBuild }
+ return generateSitemap(request, serverBuild.build.routes, {
+ siteUrl: getDomainUrl(request),
+ headers: {
+ 'Cache-Control': `public, max-age=${60 * 5}`,
+ },
+ })
+}
diff --git a/app/routes/admin+/cache.tsx b/app/routes/admin+/cache.tsx
new file mode 100644
index 0000000..741e858
--- /dev/null
+++ b/app/routes/admin+/cache.tsx
@@ -0,0 +1,249 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import {
+ Form,
+ Link,
+ useFetcher,
+ useLoaderData,
+ useSearchParams,
+ useSubmit,
+} from '@remix-run/react'
+import { GeneralErrorBoundary } from '#app/components/error-boundary'
+import { Field } from '#app/components/forms.tsx'
+import { Spacer } from '#app/components/spacer.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import {
+ cache,
+ getAllCacheKeys,
+ lruCache,
+ searchCacheKeys,
+} from '#app/utils/cache.server.ts'
+import {
+ ensureInstance,
+ getAllInstances,
+ getInstanceInfo,
+} from '#app/utils/litefs.server.ts'
+import { useDebounce, useDoubleCheck } from '#app/utils/misc.tsx'
+import { requireUserWithRole } from '#app/utils/permissions.server.ts'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ await requireUserWithRole(request, 'admin')
+ const searchParams = new URL(request.url).searchParams
+ const query = searchParams.get('query')
+ if (query === '') {
+ searchParams.delete('query')
+ return redirect(`/admin/cache?${searchParams.toString()}`)
+ }
+ const limit = Number(searchParams.get('limit') ?? 100)
+
+ const currentInstanceInfo = await getInstanceInfo()
+ const instance =
+ searchParams.get('instance') ?? currentInstanceInfo.currentInstance
+ const instances = await getAllInstances()
+ await ensureInstance(instance)
+
+ let cacheKeys: { sqlite: Array; lru: Array }
+ if (typeof query === 'string') {
+ cacheKeys = await searchCacheKeys(query, limit)
+ } else {
+ cacheKeys = await getAllCacheKeys(limit)
+ }
+ return json({ cacheKeys, instance, instances, currentInstanceInfo })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ await requireUserWithRole(request, 'admin')
+ const formData = await request.formData()
+ const key = formData.get('cacheKey')
+ const { currentInstance } = await getInstanceInfo()
+ const instance = formData.get('instance') ?? currentInstance
+ const type = formData.get('type')
+
+ invariantResponse(typeof key === 'string', 'cacheKey must be a string')
+ invariantResponse(typeof type === 'string', 'type must be a string')
+ invariantResponse(typeof instance === 'string', 'instance must be a string')
+ await ensureInstance(instance)
+
+ switch (type) {
+ case 'sqlite': {
+ await cache.delete(key)
+ break
+ }
+ case 'lru': {
+ lruCache.delete(key)
+ break
+ }
+ default: {
+ throw new Error(`Unknown cache type: ${type}`)
+ }
+ }
+ return json({ success: true })
+}
+
+export default function CacheAdminRoute() {
+ const data = useLoaderData()
+ const [searchParams] = useSearchParams()
+ const submit = useSubmit()
+ const query = searchParams.get('query') ?? ''
+ const limit = searchParams.get('limit') ?? '100'
+ const instance = searchParams.get('instance') ?? data.instance
+
+ const handleFormChange = useDebounce((form: HTMLFormElement) => {
+ submit(form)
+ }, 400)
+
+ return (
+
+
Cache Admin
+
+
+
+
+
LRU Cache:
+ {data.cacheKeys.lru.map((key) => (
+
+ ))}
+
+
+
+
SQLite Cache:
+ {data.cacheKeys.sqlite.map((key) => (
+
+ ))}
+
+
+ )
+}
+
+function CacheKeyRow({
+ cacheKey,
+ instance,
+ type,
+}: {
+ cacheKey: string
+ instance?: string
+ type: 'sqlite' | 'lru'
+}) {
+ const fetcher = useFetcher()
+ const dc = useDoubleCheck()
+ const encodedKey = encodeURIComponent(cacheKey)
+ const valuePage = `/admin/cache/${type}/${encodedKey}?instance=${instance}`
+ return (
+
+
+
+
+
+
+ {fetcher.state === 'idle'
+ ? dc.doubleCheck
+ ? 'You sure?'
+ : 'Delete'
+ : 'Deleting...'}
+
+
+
+ {cacheKey}
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return (
+ (
+ You are not allowed to do that: {error?.data.message}
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/admin+/cache_.lru.$cacheKey.ts b/app/routes/admin+/cache_.lru.$cacheKey.ts
new file mode 100644
index 0000000..2b793d0
--- /dev/null
+++ b/app/routes/admin+/cache_.lru.$cacheKey.ts
@@ -0,0 +1,31 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { lruCache } from '#app/utils/cache.server.ts'
+import {
+ getAllInstances,
+ getInstanceInfo,
+ ensureInstance,
+} from '#app/utils/litefs.server.ts'
+import { requireUserWithRole } from '#app/utils/permissions.server.ts'
+
+export async function loader({ request, params }: LoaderFunctionArgs) {
+ await requireUserWithRole(request, 'admin')
+ const searchParams = new URL(request.url).searchParams
+ const currentInstanceInfo = await getInstanceInfo()
+ const allInstances = await getAllInstances()
+ const instance =
+ searchParams.get('instance') ?? currentInstanceInfo.currentInstance
+ await ensureInstance(instance)
+
+ const { cacheKey } = params
+ invariantResponse(cacheKey, 'cacheKey is required')
+ return json({
+ instance: {
+ hostname: instance,
+ region: allInstances[instance],
+ isPrimary: currentInstanceInfo.primaryInstance === instance,
+ },
+ cacheKey,
+ value: lruCache.get(cacheKey),
+ })
+}
diff --git a/app/routes/admin+/cache_.sqlite.$cacheKey.ts b/app/routes/admin+/cache_.sqlite.$cacheKey.ts
new file mode 100644
index 0000000..39bcb07
--- /dev/null
+++ b/app/routes/admin+/cache_.sqlite.$cacheKey.ts
@@ -0,0 +1,31 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { cache } from '#app/utils/cache.server.ts'
+import {
+ getAllInstances,
+ getInstanceInfo,
+ ensureInstance,
+} from '#app/utils/litefs.server.ts'
+import { requireUserWithRole } from '#app/utils/permissions.server.ts'
+
+export async function loader({ request, params }: LoaderFunctionArgs) {
+ await requireUserWithRole(request, 'admin')
+ const searchParams = new URL(request.url).searchParams
+ const currentInstanceInfo = await getInstanceInfo()
+ const allInstances = await getAllInstances()
+ const instance =
+ searchParams.get('instance') ?? currentInstanceInfo.currentInstance
+ await ensureInstance(instance)
+
+ const { cacheKey } = params
+ invariantResponse(cacheKey, 'cacheKey is required')
+ return json({
+ instance: {
+ hostname: instance,
+ region: allInstances[instance],
+ isPrimary: currentInstanceInfo.primaryInstance === instance,
+ },
+ cacheKey,
+ value: cache.get(cacheKey),
+ })
+}
diff --git a/app/routes/admin+/cache_.sqlite.server.ts b/app/routes/admin+/cache_.sqlite.server.ts
new file mode 100644
index 0000000..a9c8f80
--- /dev/null
+++ b/app/routes/admin+/cache_.sqlite.server.ts
@@ -0,0 +1,58 @@
+import { json, redirect, type ActionFunctionArgs } from '@remix-run/node'
+import { z } from 'zod'
+import { cache } from '#app/utils/cache.server.ts'
+import {
+ getInstanceInfo,
+ getInternalInstanceDomain,
+} from '#app/utils/litefs.server'
+
+export async function updatePrimaryCacheValue({
+ key,
+ cacheValue,
+}: {
+ key: string
+ cacheValue: any
+}) {
+ const { currentIsPrimary, primaryInstance } = await getInstanceInfo()
+ if (currentIsPrimary) {
+ throw new Error(
+ `updatePrimaryCacheValue should not be called on the primary instance (${primaryInstance})}`,
+ )
+ }
+ const domain = getInternalInstanceDomain(primaryInstance)
+ const token = process.env.INTERNAL_COMMAND_TOKEN
+ return fetch(`${domain}/admin/cache/sqlite`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${token}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ key, cacheValue }),
+ })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const { currentIsPrimary, primaryInstance } = await getInstanceInfo()
+ if (!currentIsPrimary) {
+ throw new Error(
+ `${request.url} should only be called on the primary instance (${primaryInstance})}`,
+ )
+ }
+ const token = process.env.INTERNAL_COMMAND_TOKEN
+ const isAuthorized =
+ request.headers.get('Authorization') === `Bearer ${token}`
+ if (!isAuthorized) {
+ // nah, you can't be here...
+ return redirect('https://www.youtube.com/watch?v=dQw4w9WgXcQ')
+ }
+ const { key, cacheValue } = z
+ .object({ key: z.string(), cacheValue: z.unknown().optional() })
+ .parse(await request.json())
+ if (cacheValue === undefined) {
+ await cache.delete(key)
+ } else {
+ // @ts-expect-error - we don't reliably know the type of cacheValue
+ await cache.set(key, cacheValue)
+ }
+ return json({ success: true })
+}
diff --git a/app/routes/admin+/cache_.sqlite.tsx b/app/routes/admin+/cache_.sqlite.tsx
new file mode 100644
index 0000000..e469891
--- /dev/null
+++ b/app/routes/admin+/cache_.sqlite.tsx
@@ -0,0 +1 @@
+export { action } from './cache_.sqlite.server.ts'
diff --git a/app/routes/me.tsx b/app/routes/me.tsx
new file mode 100644
index 0000000..28eb14c
--- /dev/null
+++ b/app/routes/me.tsx
@@ -0,0 +1,18 @@
+import { redirect, type LoaderFunctionArgs } from '@remix-run/node'
+import { requireUserId, logout } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findUnique({ where: { id: userId } })
+ if (!user) {
+ const requestUrl = new URL(request.url)
+ const loginParams = new URLSearchParams([
+ ['redirectTo', `${requestUrl.pathname}${requestUrl.search}`],
+ ])
+ const redirectTo = `/login?${loginParams}`
+ await logout({ request, redirectTo })
+ return redirect(redirectTo)
+ }
+ return redirect(`/users/${user.username}`)
+}
diff --git a/app/routes/resources+/download-user-data.tsx b/app/routes/resources+/download-user-data.tsx
new file mode 100644
index 0000000..edd8df4
--- /dev/null
+++ b/app/routes/resources+/download-user-data.tsx
@@ -0,0 +1,62 @@
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { getDomainUrl } from '#app/utils/misc.tsx'
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findUniqueOrThrow({
+ where: { id: userId },
+ // this is one of the *few* instances where you can use "include" because
+ // the goal is to literally get *everything*. Normally you should be
+ // explicit with "select". We're using select for images because we don't
+ // want to send back the entire blob of the image. We'll send a URL they can
+ // use to download it instead.
+ include: {
+ image: {
+ select: {
+ id: true,
+ createdAt: true,
+ updatedAt: true,
+ contentType: true,
+ },
+ },
+ notes: {
+ include: {
+ images: {
+ select: {
+ id: true,
+ createdAt: true,
+ updatedAt: true,
+ contentType: true,
+ },
+ },
+ },
+ },
+ password: false, // <-- intentionally omit password
+ sessions: true,
+ roles: true,
+ },
+ })
+
+ const domain = getDomainUrl(request)
+
+ return json({
+ user: {
+ ...user,
+ image: user.image
+ ? {
+ ...user.image,
+ url: `${domain}/resources/user-images/${user.image.id}`,
+ }
+ : null,
+ notes: user.notes.map((note) => ({
+ ...note,
+ images: note.images.map((image) => ({
+ ...image,
+ url: `${domain}/resources/note-images/${image.id}`,
+ })),
+ })),
+ },
+ })
+}
diff --git a/app/routes/resources+/healthcheck.tsx b/app/routes/resources+/healthcheck.tsx
new file mode 100644
index 0000000..435a247
--- /dev/null
+++ b/app/routes/resources+/healthcheck.tsx
@@ -0,0 +1,26 @@
+// learn more: https://fly.io/docs/reference/configuration/#services-http_checks
+import { type LoaderFunctionArgs } from '@remix-run/node'
+import { prisma } from '#app/utils/db.server.ts'
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const host =
+ request.headers.get('X-Forwarded-Host') ?? request.headers.get('host')
+
+ try {
+ // if we can connect to the database and make a simple query
+ // and make a HEAD request to ourselves, then we're good.
+ await Promise.all([
+ prisma.user.count(),
+ fetch(`${new URL(request.url).protocol}${host}`, {
+ method: 'HEAD',
+ headers: { 'X-Healthcheck': 'true' },
+ }).then((r) => {
+ if (!r.ok) return Promise.reject(r)
+ }),
+ ])
+ return new Response('OK')
+ } catch (error: unknown) {
+ console.log('healthcheck â', { error })
+ return new Response('ERROR', { status: 500 })
+ }
+}
diff --git a/app/routes/resources+/note-images.$imageId.tsx b/app/routes/resources+/note-images.$imageId.tsx
new file mode 100644
index 0000000..7c4b84c
--- /dev/null
+++ b/app/routes/resources+/note-images.$imageId.tsx
@@ -0,0 +1,22 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { type LoaderFunctionArgs } from '@remix-run/node'
+import { prisma } from '#app/utils/db.server.ts'
+
+export async function loader({ params }: LoaderFunctionArgs) {
+ invariantResponse(params.imageId, 'Image ID is required', { status: 400 })
+ const image = await prisma.noteImage.findUnique({
+ where: { id: params.imageId },
+ select: { contentType: true, blob: true },
+ })
+
+ invariantResponse(image, 'Not found', { status: 404 })
+
+ return new Response(image.blob, {
+ headers: {
+ 'Content-Type': image.contentType,
+ 'Content-Length': Buffer.byteLength(image.blob).toString(),
+ 'Content-Disposition': `inline; filename="${params.imageId}"`,
+ 'Cache-Control': 'public, max-age=31536000, immutable',
+ },
+ })
+}
diff --git a/app/routes/resources+/theme-switch.tsx b/app/routes/resources+/theme-switch.tsx
new file mode 100644
index 0000000..5ea2aea
--- /dev/null
+++ b/app/routes/resources+/theme-switch.tsx
@@ -0,0 +1,131 @@
+import { useForm, getFormProps } from '@conform-to/react'
+import { parseWithZod } from '@conform-to/zod'
+import { invariantResponse } from '@epic-web/invariant'
+import { json, type ActionFunctionArgs } from '@remix-run/node'
+import { redirect, useFetcher, useFetchers } from '@remix-run/react'
+import { ServerOnly } from 'remix-utils/server-only'
+import { z } from 'zod'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { useHints } from '#app/utils/client-hints.tsx'
+import { useRequestInfo } from '#app/utils/request-info.ts'
+import { type Theme, setTheme } from '#app/utils/theme.server.ts'
+
+const ThemeFormSchema = z.object({
+ theme: z.enum(['system', 'light', 'dark']),
+ // this is useful for progressive enhancement
+ redirectTo: z.string().optional(),
+})
+
+export async function action({ request }: ActionFunctionArgs) {
+ const formData = await request.formData()
+ const submission = parseWithZod(formData, {
+ schema: ThemeFormSchema,
+ })
+
+ invariantResponse(submission.status === 'success', 'Invalid theme received')
+
+ const { theme, redirectTo } = submission.value
+
+ const responseInit = {
+ headers: { 'set-cookie': setTheme(theme) },
+ }
+ if (redirectTo) {
+ return redirect(redirectTo, responseInit)
+ } else {
+ return json({ result: submission.reply() }, responseInit)
+ }
+}
+
+export function ThemeSwitch({
+ userPreference,
+}: {
+ userPreference?: Theme | null
+}) {
+ const fetcher = useFetcher()
+ const requestInfo = useRequestInfo()
+
+ const [form] = useForm({
+ id: 'theme-switch',
+ lastResult: fetcher.data?.result,
+ })
+
+ const optimisticMode = useOptimisticThemeMode()
+ const mode = optimisticMode ?? userPreference ?? 'system'
+ const nextMode =
+ mode === 'system' ? 'light' : mode === 'light' ? 'dark' : 'system'
+ const modeLabel = {
+ light: (
+
+ Light
+
+ ),
+ dark: (
+
+ Dark
+
+ ),
+ system: (
+
+ System
+
+ ),
+ }
+
+ return (
+
+
+ {() => (
+
+ )}
+
+
+
+
+ {modeLabel[mode]}
+
+
+
+ )
+}
+
+/**
+ * If the user's changing their theme mode preference, this will return the
+ * value it's being changed to.
+ */
+export function useOptimisticThemeMode() {
+ const fetchers = useFetchers()
+ const themeFetcher = fetchers.find(
+ (f) => f.formAction === '/resources/theme-switch',
+ )
+
+ if (themeFetcher && themeFetcher.formData) {
+ const submission = parseWithZod(themeFetcher.formData, {
+ schema: ThemeFormSchema,
+ })
+
+ if (submission.status === 'success') {
+ return submission.value.theme
+ }
+ }
+}
+
+/**
+ * @returns the user's theme preference, or the client hint theme if the user
+ * has not set a preference.
+ */
+export function useTheme() {
+ const hints = useHints()
+ const requestInfo = useRequestInfo()
+ const optimisticMode = useOptimisticThemeMode()
+ if (optimisticMode) {
+ return optimisticMode === 'system' ? hints.theme : optimisticMode
+ }
+ return requestInfo.userPrefs.theme ?? hints.theme
+}
diff --git a/app/routes/resources+/user-images.$imageId.tsx b/app/routes/resources+/user-images.$imageId.tsx
new file mode 100644
index 0000000..19a12af
--- /dev/null
+++ b/app/routes/resources+/user-images.$imageId.tsx
@@ -0,0 +1,22 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { type LoaderFunctionArgs } from '@remix-run/node'
+import { prisma } from '#app/utils/db.server.ts'
+
+export async function loader({ params }: LoaderFunctionArgs) {
+ invariantResponse(params.imageId, 'Image ID is required', { status: 400 })
+ const image = await prisma.userImage.findUnique({
+ where: { id: params.imageId },
+ select: { contentType: true, blob: true },
+ })
+
+ invariantResponse(image, 'Not found', { status: 404 })
+
+ return new Response(image.blob, {
+ headers: {
+ 'Content-Type': image.contentType,
+ 'Content-Length': Buffer.byteLength(image.blob).toString(),
+ 'Content-Disposition': `inline; filename="${params.imageId}"`,
+ 'Cache-Control': 'public, max-age=31536000, immutable',
+ },
+ })
+}
diff --git a/app/routes/settings+/profile.change-email.server.tsx b/app/routes/settings+/profile.change-email.server.tsx
new file mode 100644
index 0000000..0a0eebc
--- /dev/null
+++ b/app/routes/settings+/profile.change-email.server.tsx
@@ -0,0 +1,124 @@
+import { invariant } from '@epic-web/invariant'
+import * as E from '@react-email/components'
+import { json } from '@remix-run/node'
+import {
+ requireRecentVerification,
+ type VerifyFunctionArgs,
+} from '#app/routes/_auth+/verify.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { sendEmail } from '#app/utils/email.server.ts'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { newEmailAddressSessionKey } from './profile.change-email'
+
+export async function handleVerification({
+ request,
+ submission,
+}: VerifyFunctionArgs) {
+ await requireRecentVerification(request)
+ invariant(
+ submission.status === 'success',
+ 'Submission should be successful by now',
+ )
+
+ const verifySession = await verifySessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const newEmail = verifySession.get(newEmailAddressSessionKey)
+ if (!newEmail) {
+ return json(
+ {
+ result: submission.reply({
+ formErrors: [
+ 'You must submit the code on the same device that requested the email change.',
+ ],
+ }),
+ },
+ { status: 400 },
+ )
+ }
+ const preUpdateUser = await prisma.user.findFirstOrThrow({
+ select: { email: true },
+ where: { id: submission.value.target },
+ })
+ const user = await prisma.user.update({
+ where: { id: submission.value.target },
+ select: { id: true, email: true, username: true },
+ data: { email: newEmail },
+ })
+
+ void sendEmail({
+ to: preUpdateUser.email,
+ subject: 'Epic Stack email changed',
+ react: ,
+ })
+
+ return redirectWithToast(
+ '/settings/profile',
+ {
+ title: 'Email Changed',
+ type: 'success',
+ description: `Your email has been changed to ${user.email}`,
+ },
+ {
+ headers: {
+ 'set-cookie': await verifySessionStorage.destroySession(verifySession),
+ },
+ },
+ )
+}
+
+export function EmailChangeEmail({
+ verifyUrl,
+ otp,
+}: {
+ verifyUrl: string
+ otp: string
+}) {
+ return (
+
+
+
+ Epic Notes Email Change
+
+
+
+ Here's your verification code: {otp}
+
+
+
+ Or click the link:
+
+ {verifyUrl}
+
+
+ )
+}
+
+function EmailChangeNoticeEmail({ userId }: { userId: string }) {
+ return (
+
+
+
+ Your Epic Notes email has been changed
+
+
+
+ We're writing to let you know that your Epic Notes email has been
+ changed.
+
+
+
+
+ If you changed your email address, then you can safely ignore this.
+ But if you did not change your email address, then please contact
+ support immediately.
+
+
+
+ Your Account ID: {userId}
+
+
+
+ )
+}
diff --git a/app/routes/settings+/profile.change-email.tsx b/app/routes/settings+/profile.change-email.tsx
new file mode 100644
index 0000000..e687588
--- /dev/null
+++ b/app/routes/settings+/profile.change-email.tsx
@@ -0,0 +1,150 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type ActionFunctionArgs,
+ type LoaderFunctionArgs,
+} from '@remix-run/node'
+import { Form, useActionData, useLoaderData } from '@remix-run/react'
+import { z } from 'zod'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import {
+ prepareVerification,
+ requireRecentVerification,
+} from '#app/routes/_auth+/verify.server.ts'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { sendEmail } from '#app/utils/email.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { EmailSchema } from '#app/utils/user-validation.ts'
+import { verifySessionStorage } from '#app/utils/verification.server.ts'
+import { EmailChangeEmail } from './profile.change-email.server.tsx'
+import { type BreadcrumbHandle } from './profile.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Change Email ,
+ getSitemapEntries: () => null,
+}
+
+export const newEmailAddressSessionKey = 'new-email-address'
+
+const ChangeEmailSchema = z.object({
+ email: EmailSchema,
+})
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ await requireRecentVerification(request)
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findUnique({
+ where: { id: userId },
+ select: { email: true },
+ })
+ if (!user) {
+ const params = new URLSearchParams({ redirectTo: request.url })
+ throw redirect(`/login?${params}`)
+ }
+ return json({ user })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const formData = await request.formData()
+ const submission = await parseWithZod(formData, {
+ schema: ChangeEmailSchema.superRefine(async (data, ctx) => {
+ const existingUser = await prisma.user.findUnique({
+ where: { email: data.email },
+ })
+ if (existingUser) {
+ ctx.addIssue({
+ path: ['email'],
+ code: z.ZodIssueCode.custom,
+ message: 'This email is already in use.',
+ })
+ }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+ const { otp, redirectTo, verifyUrl } = await prepareVerification({
+ period: 10 * 60,
+ request,
+ target: userId,
+ type: 'change-email',
+ })
+
+ const response = await sendEmail({
+ to: submission.value.email,
+ subject: `Epic Notes Email Change Verification`,
+ react: ,
+ })
+
+ if (response.status === 'success') {
+ const verifySession = await verifySessionStorage.getSession()
+ verifySession.set(newEmailAddressSessionKey, submission.value.email)
+ return redirect(redirectTo.toString(), {
+ headers: {
+ 'set-cookie': await verifySessionStorage.commitSession(verifySession),
+ },
+ })
+ } else {
+ return json(
+ { result: submission.reply({ formErrors: [response.error.message] }) },
+ { status: 500 },
+ )
+ }
+}
+
+export default function ChangeEmailIndex() {
+ const data = useLoaderData()
+ const actionData = useActionData()
+
+ const [form, fields] = useForm({
+ id: 'change-email-form',
+ constraint: getZodConstraint(ChangeEmailSchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: ChangeEmailSchema })
+ },
+ })
+
+ const isPending = useIsPending()
+ return (
+
+
Change Email
+
You will receive an email at the new email address to confirm.
+
+ An email notice will also be sent to your old address {data.user.email}.
+
+
+
+ )
+}
diff --git a/app/routes/settings+/profile.connections.tsx b/app/routes/settings+/profile.connections.tsx
new file mode 100644
index 0000000..91c4795
--- /dev/null
+++ b/app/routes/settings+/profile.connections.tsx
@@ -0,0 +1,224 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+ type SerializeFrom,
+ type HeadersFunction,
+} from '@remix-run/node'
+import { useFetcher, useLoaderData } from '@remix-run/react'
+import { useState } from 'react'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipProvider,
+ TooltipTrigger,
+} from '#app/components/ui/tooltip.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { resolveConnectionData } from '#app/utils/connections.server.ts'
+import {
+ ProviderConnectionForm,
+ type ProviderName,
+ ProviderNameSchema,
+ providerIcons,
+ providerNames,
+} from '#app/utils/connections.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { makeTimings } from '#app/utils/timing.server.ts'
+import { createToastHeaders } from '#app/utils/toast.server.ts'
+import { type BreadcrumbHandle } from './profile.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Connections ,
+ getSitemapEntries: () => null,
+}
+
+async function userCanDeleteConnections(userId: string) {
+ const user = await prisma.user.findUnique({
+ select: {
+ password: { select: { userId: true } },
+ _count: { select: { connections: true } },
+ },
+ where: { id: userId },
+ })
+ // user can delete their connections if they have a password
+ if (user?.password) return true
+ // users have to have more than one remaining connection to delete one
+ return Boolean(user?._count.connections && user?._count.connections > 1)
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const timings = makeTimings('profile connections loader')
+ const rawConnections = await prisma.connection.findMany({
+ select: { id: true, providerName: true, providerId: true, createdAt: true },
+ where: { userId },
+ })
+ const connections: Array<{
+ providerName: ProviderName
+ id: string
+ displayName: string
+ link?: string | null
+ createdAtFormatted: string
+ }> = []
+ for (const connection of rawConnections) {
+ const r = ProviderNameSchema.safeParse(connection.providerName)
+ if (!r.success) continue
+ const providerName = r.data
+ const connectionData = await resolveConnectionData(
+ providerName,
+ connection.providerId,
+ { timings },
+ )
+ connections.push({
+ ...connectionData,
+ providerName,
+ id: connection.id,
+ createdAtFormatted: connection.createdAt.toLocaleString(),
+ })
+ }
+
+ return json(
+ {
+ connections,
+ canDeleteConnections: await userCanDeleteConnections(userId),
+ },
+ { headers: { 'Server-Timing': timings.toString() } },
+ )
+}
+
+export const headers: HeadersFunction = ({ loaderHeaders }) => {
+ const headers = {
+ 'Server-Timing': loaderHeaders.get('Server-Timing') ?? '',
+ }
+ return headers
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const formData = await request.formData()
+ invariantResponse(
+ formData.get('intent') === 'delete-connection',
+ 'Invalid intent',
+ )
+ invariantResponse(
+ await userCanDeleteConnections(userId),
+ 'You cannot delete your last connection unless you have a password.',
+ )
+ const connectionId = formData.get('connectionId')
+ invariantResponse(typeof connectionId === 'string', 'Invalid connectionId')
+ await prisma.connection.delete({
+ where: {
+ id: connectionId,
+ userId: userId,
+ },
+ })
+ const toastHeaders = await createToastHeaders({
+ title: 'Deleted',
+ description: 'Your connection has been deleted.',
+ })
+ return json({ status: 'success' } as const, { headers: toastHeaders })
+}
+
+export default function Connections() {
+ const data = useLoaderData()
+
+ return (
+
+ {data.connections.length ? (
+
+
Here are your current connections:
+
+ {data.connections.map((c) => (
+
+
+
+ ))}
+
+
+ ) : (
+
You don't have any connections yet.
+ )}
+
+ {providerNames.map((providerName) => (
+
+ ))}
+
+
+ )
+}
+
+function Connection({
+ connection,
+ canDelete,
+}: {
+ connection: SerializeFrom['connections'][number]
+ canDelete: boolean
+}) {
+ const deleteFetcher = useFetcher()
+ const [infoOpen, setInfoOpen] = useState(false)
+ const icon = providerIcons[connection.providerName]
+ return (
+
+
+ {icon}
+
+ {connection.link ? (
+
+ {connection.displayName}
+
+ ) : (
+ connection.displayName
+ )}{' '}
+ ({connection.createdAtFormatted})
+
+
+ {canDelete ? (
+
+
+
+
+
+
+
+
+
+ Disconnect this account
+
+
+
+ ) : (
+
+
+ setInfoOpen(true)}>
+
+
+
+ You cannot delete your last connection unless you have a password.
+
+
+
+ )}
+
+ )
+}
diff --git a/app/routes/settings+/profile.index.tsx b/app/routes/settings+/profile.index.tsx
new file mode 100644
index 0000000..380cfa2
--- /dev/null
+++ b/app/routes/settings+/profile.index.tsx
@@ -0,0 +1,363 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { invariantResponse } from '@epic-web/invariant'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import { Link, useFetcher, useLoaderData } from '@remix-run/react'
+import { z } from 'zod'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireUserId, sessionKey } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { getUserImgSrc, useDoubleCheck } from '#app/utils/misc.tsx'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { NameSchema, UsernameSchema } from '#app/utils/user-validation.ts'
+import { twoFAVerificationType } from './profile.two-factor.tsx'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+const ProfileFormSchema = z.object({
+ name: NameSchema.optional(),
+ username: UsernameSchema,
+})
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findUniqueOrThrow({
+ where: { id: userId },
+ select: {
+ id: true,
+ name: true,
+ username: true,
+ email: true,
+ image: {
+ select: { id: true },
+ },
+ _count: {
+ select: {
+ sessions: {
+ where: {
+ expirationDate: { gt: new Date() },
+ },
+ },
+ },
+ },
+ },
+ })
+
+ const twoFactorVerification = await prisma.verification.findUnique({
+ select: { id: true },
+ where: { target_type: { type: twoFAVerificationType, target: userId } },
+ })
+
+ const password = await prisma.password.findUnique({
+ select: { userId: true },
+ where: { userId },
+ })
+
+ return json({
+ user,
+ hasPassword: Boolean(password),
+ isTwoFactorEnabled: Boolean(twoFactorVerification),
+ })
+}
+
+type ProfileActionArgs = {
+ request: Request
+ userId: string
+ formData: FormData
+}
+const profileUpdateActionIntent = 'update-profile'
+const signOutOfSessionsActionIntent = 'sign-out-of-sessions'
+const deleteDataActionIntent = 'delete-data'
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const formData = await request.formData()
+ const intent = formData.get('intent')
+ switch (intent) {
+ case profileUpdateActionIntent: {
+ return profileUpdateAction({ request, userId, formData })
+ }
+ case signOutOfSessionsActionIntent: {
+ return signOutOfSessionsAction({ request, userId, formData })
+ }
+ case deleteDataActionIntent: {
+ return deleteDataAction({ request, userId, formData })
+ }
+ default: {
+ throw new Response(`Invalid intent "${intent}"`, { status: 400 })
+ }
+ }
+}
+
+export default function EditUserProfile() {
+ const data = useLoaderData()
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Change email from {data.user.email}
+
+
+
+
+
+ {data.isTwoFactorEnabled ? (
+ 2FA is enabled
+ ) : (
+ Enable 2FA
+ )}
+
+
+
+
+
+ {data.hasPassword ? 'Change Password' : 'Create a Password'}
+
+
+
+
+
+ Manage connections
+
+
+
+
+ Download your data
+
+
+
+
+
+
+ )
+}
+
+async function profileUpdateAction({ userId, formData }: ProfileActionArgs) {
+ const submission = await parseWithZod(formData, {
+ async: true,
+ schema: ProfileFormSchema.superRefine(async ({ username }, ctx) => {
+ const existingUsername = await prisma.user.findUnique({
+ where: { username },
+ select: { id: true },
+ })
+ if (existingUsername && existingUsername.id !== userId) {
+ ctx.addIssue({
+ path: ['username'],
+ code: z.ZodIssueCode.custom,
+ message: 'A user already exists with this username',
+ })
+ }
+ }),
+ })
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const data = submission.value
+
+ await prisma.user.update({
+ select: { username: true },
+ where: { id: userId },
+ data: {
+ name: data.name,
+ username: data.username,
+ },
+ })
+
+ return json({
+ result: submission.reply(),
+ })
+}
+
+function UpdateProfile() {
+ const data = useLoaderData()
+
+ const fetcher = useFetcher()
+
+ const [form, fields] = useForm({
+ id: 'edit-profile',
+ constraint: getZodConstraint(ProfileFormSchema),
+ lastResult: fetcher.data?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: ProfileFormSchema })
+ },
+ defaultValue: {
+ username: data.user.username,
+ name: data.user.name,
+ },
+ })
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ Save changes
+
+
+
+ )
+}
+
+async function signOutOfSessionsAction({ request, userId }: ProfileActionArgs) {
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const sessionId = authSession.get(sessionKey)
+ invariantResponse(
+ sessionId,
+ 'You must be authenticated to sign out of other sessions',
+ )
+ await prisma.session.deleteMany({
+ where: {
+ userId,
+ id: { not: sessionId },
+ },
+ })
+ return json({ status: 'success' } as const)
+}
+
+function SignOutOfSessions() {
+ const data = useLoaderData()
+ const dc = useDoubleCheck()
+
+ const fetcher = useFetcher()
+ const otherSessionsCount = data.user._count.sessions - 1
+ return (
+
+ {otherSessionsCount ? (
+
+
+
+ {dc.doubleCheck
+ ? `Are you sure?`
+ : `Sign out of ${otherSessionsCount} other sessions`}
+
+
+
+ ) : (
+ This is your only session
+ )}
+
+ )
+}
+
+async function deleteDataAction({ userId }: ProfileActionArgs) {
+ await prisma.user.delete({ where: { id: userId } })
+ return redirectWithToast('/', {
+ type: 'success',
+ title: 'Data Deleted',
+ description: 'All of your data has been deleted',
+ })
+}
+
+function DeleteData() {
+ const dc = useDoubleCheck()
+
+ const fetcher = useFetcher()
+ return (
+
+
+
+
+ {dc.doubleCheck ? `Are you sure?` : `Delete all your data`}
+
+
+
+
+ )
+}
diff --git a/app/routes/settings+/profile.password.tsx b/app/routes/settings+/profile.password.tsx
new file mode 100644
index 0000000..afdf7af
--- /dev/null
+++ b/app/routes/settings+/profile.password.tsx
@@ -0,0 +1,177 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import { Form, Link, useActionData } from '@remix-run/react'
+import { z } from 'zod'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import {
+ getPasswordHash,
+ requireUserId,
+ verifyUserPassword,
+} from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { PasswordSchema } from '#app/utils/user-validation.ts'
+import { type BreadcrumbHandle } from './profile.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Password ,
+ getSitemapEntries: () => null,
+}
+
+const ChangePasswordForm = z
+ .object({
+ currentPassword: PasswordSchema,
+ newPassword: PasswordSchema,
+ confirmNewPassword: PasswordSchema,
+ })
+ .superRefine(({ confirmNewPassword, newPassword }, ctx) => {
+ if (confirmNewPassword !== newPassword) {
+ ctx.addIssue({
+ path: ['confirmNewPassword'],
+ code: z.ZodIssueCode.custom,
+ message: 'The passwords must match',
+ })
+ }
+ })
+
+async function requirePassword(userId: string) {
+ const password = await prisma.password.findUnique({
+ select: { userId: true },
+ where: { userId },
+ })
+ if (!password) {
+ throw redirect('/settings/profile/password/create')
+ }
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ await requirePassword(userId)
+ return json({})
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ await requirePassword(userId)
+ const formData = await request.formData()
+ const submission = await parseWithZod(formData, {
+ async: true,
+ schema: ChangePasswordForm.superRefine(
+ async ({ currentPassword, newPassword }, ctx) => {
+ if (currentPassword && newPassword) {
+ const user = await verifyUserPassword({ id: userId }, currentPassword)
+ if (!user) {
+ ctx.addIssue({
+ path: ['currentPassword'],
+ code: z.ZodIssueCode.custom,
+ message: 'Incorrect password.',
+ })
+ }
+ }
+ },
+ ),
+ })
+ if (submission.status !== 'success') {
+ return json(
+ {
+ result: submission.reply({
+ hideFields: ['currentPassword', 'newPassword', 'confirmNewPassword'],
+ }),
+ },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { newPassword } = submission.value
+
+ await prisma.user.update({
+ select: { username: true },
+ where: { id: userId },
+ data: {
+ password: {
+ update: {
+ hash: await getPasswordHash(newPassword),
+ },
+ },
+ },
+ })
+
+ return redirectWithToast(
+ `/settings/profile`,
+ {
+ type: 'success',
+ title: 'Password Changed',
+ description: 'Your password has been changed.',
+ },
+ { status: 302 },
+ )
+}
+
+export default function ChangePasswordRoute() {
+ const actionData = useActionData()
+ const isPending = useIsPending()
+
+ const [form, fields] = useForm({
+ id: 'password-change-form',
+ constraint: getZodConstraint(ChangePasswordForm),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: ChangePasswordForm })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+ )
+}
diff --git a/app/routes/settings+/profile.password_.create.tsx b/app/routes/settings+/profile.password_.create.tsx
new file mode 100644
index 0000000..24770f8
--- /dev/null
+++ b/app/routes/settings+/profile.password_.create.tsx
@@ -0,0 +1,128 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import { Form, Link, useActionData } from '@remix-run/react'
+import { ErrorList, Field } from '#app/components/forms.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { getPasswordHash, requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { useIsPending } from '#app/utils/misc.tsx'
+import { PasswordAndConfirmPasswordSchema } from '#app/utils/user-validation.ts'
+import { type BreadcrumbHandle } from './profile.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Password ,
+ getSitemapEntries: () => null,
+}
+
+const CreatePasswordForm = PasswordAndConfirmPasswordSchema
+
+async function requireNoPassword(userId: string) {
+ const password = await prisma.password.findUnique({
+ select: { userId: true },
+ where: { userId },
+ })
+ if (password) {
+ throw redirect('/settings/profile/password')
+ }
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ await requireNoPassword(userId)
+ return json({})
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ await requireNoPassword(userId)
+ const formData = await request.formData()
+ const submission = await parseWithZod(formData, {
+ async: true,
+ schema: CreatePasswordForm,
+ })
+ if (submission.status !== 'success') {
+ return json(
+ {
+ result: submission.reply({
+ hideFields: ['password', 'confirmPassword'],
+ }),
+ },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { password } = submission.value
+
+ await prisma.user.update({
+ select: { username: true },
+ where: { id: userId },
+ data: {
+ password: {
+ create: {
+ hash: await getPasswordHash(password),
+ },
+ },
+ },
+ })
+
+ return redirect(`/settings/profile`, { status: 302 })
+}
+
+export default function CreatePasswordRoute() {
+ const actionData = useActionData()
+ const isPending = useIsPending()
+
+ const [form, fields] = useForm({
+ id: 'password-create-form',
+ constraint: getZodConstraint(CreatePasswordForm),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: CreatePasswordForm })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ return (
+
+ )
+}
diff --git a/app/routes/settings+/profile.photo.tsx b/app/routes/settings+/profile.photo.tsx
new file mode 100644
index 0000000..5a9718b
--- /dev/null
+++ b/app/routes/settings+/profile.photo.tsx
@@ -0,0 +1,247 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { invariantResponse } from '@epic-web/invariant'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ unstable_createMemoryUploadHandler,
+ unstable_parseMultipartFormData,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import {
+ Form,
+ useActionData,
+ useLoaderData,
+ useNavigation,
+} from '@remix-run/react'
+import { useState } from 'react'
+import { z } from 'zod'
+import { ErrorList } from '#app/components/forms.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import {
+ getUserImgSrc,
+ useDoubleCheck,
+ useIsPending,
+} from '#app/utils/misc.tsx'
+import { type BreadcrumbHandle } from './profile.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Photo ,
+ getSitemapEntries: () => null,
+}
+
+const MAX_SIZE = 1024 * 1024 * 3 // 3MB
+
+const DeleteImageSchema = z.object({
+ intent: z.literal('delete'),
+})
+
+const NewImageSchema = z.object({
+ intent: z.literal('submit'),
+ photoFile: z
+ .instanceof(File)
+ .refine((file) => file.size > 0, 'Image is required')
+ .refine(
+ (file) => file.size <= MAX_SIZE,
+ 'Image size must be less than 3MB',
+ ),
+})
+
+const PhotoFormSchema = z.discriminatedUnion('intent', [
+ DeleteImageSchema,
+ NewImageSchema,
+])
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findUnique({
+ where: { id: userId },
+ select: {
+ id: true,
+ name: true,
+ username: true,
+ image: { select: { id: true } },
+ },
+ })
+ invariantResponse(user, 'User not found', { status: 404 })
+ return json({ user })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const formData = await unstable_parseMultipartFormData(
+ request,
+ unstable_createMemoryUploadHandler({ maxPartSize: MAX_SIZE }),
+ )
+
+ const submission = await parseWithZod(formData, {
+ schema: PhotoFormSchema.transform(async (data) => {
+ if (data.intent === 'delete') return { intent: 'delete' }
+ if (data.photoFile.size <= 0) return z.NEVER
+ return {
+ intent: data.intent,
+ image: {
+ contentType: data.photoFile.type,
+ blob: Buffer.from(await data.photoFile.arrayBuffer()),
+ },
+ }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { image, intent } = submission.value
+
+ if (intent === 'delete') {
+ await prisma.userImage.deleteMany({ where: { userId } })
+ return redirect('/settings/profile')
+ }
+
+ await prisma.$transaction(async ($prisma) => {
+ await $prisma.userImage.deleteMany({ where: { userId } })
+ await $prisma.user.update({
+ where: { id: userId },
+ data: { image: { create: image } },
+ })
+ })
+
+ return redirect('/settings/profile')
+}
+
+export default function PhotoRoute() {
+ const data = useLoaderData()
+
+ const doubleCheckDeleteImage = useDoubleCheck()
+
+ const actionData = useActionData()
+ const navigation = useNavigation()
+
+ const [form, fields] = useForm({
+ id: 'profile-photo',
+ constraint: getZodConstraint(PhotoFormSchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: PhotoFormSchema })
+ },
+ shouldRevalidate: 'onBlur',
+ })
+
+ const isPending = useIsPending()
+ const pendingIntent = isPending ? navigation.formData?.get('intent') : null
+ const lastSubmissionIntent = fields.intent.value
+
+ const [newImageSrc, setNewImageSrc] = useState(null)
+
+ return (
+
+ )
+}
diff --git a/app/routes/settings+/profile.tsx b/app/routes/settings+/profile.tsx
new file mode 100644
index 0000000..711aa90
--- /dev/null
+++ b/app/routes/settings+/profile.tsx
@@ -0,0 +1,80 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { Link, Outlet, useMatches } from '@remix-run/react'
+import { z } from 'zod'
+import { Spacer } from '#app/components/spacer.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { cn } from '#app/utils/misc.tsx'
+import { useUser } from '#app/utils/user.ts'
+
+export const BreadcrumbHandle = z.object({ breadcrumb: z.any() })
+export type BreadcrumbHandle = z.infer
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Edit Profile ,
+ getSitemapEntries: () => null,
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findUnique({
+ where: { id: userId },
+ select: { username: true },
+ })
+ invariantResponse(user, 'User not found', { status: 404 })
+ return json({})
+}
+
+const BreadcrumbHandleMatch = z.object({
+ handle: BreadcrumbHandle,
+})
+
+export default function EditUserProfile() {
+ const user = useUser()
+ const matches = useMatches()
+ const breadcrumbs = matches
+ .map((m) => {
+ const result = BreadcrumbHandleMatch.safeParse(m)
+ if (!result.success || !result.data.handle.breadcrumb) return null
+ return (
+
+ {result.data.handle.breadcrumb}
+
+ )
+ })
+ .filter(Boolean)
+
+ return (
+
+
+
+
+
+ Profile
+
+
+ {breadcrumbs.map((breadcrumb, i, arr) => (
+
+ âśď¸ {breadcrumb}
+
+ ))}
+
+
+
+
+
+
+
+ )
+}
diff --git a/app/routes/settings+/profile.two-factor.disable.tsx b/app/routes/settings+/profile.two-factor.disable.tsx
new file mode 100644
index 0000000..f153099
--- /dev/null
+++ b/app/routes/settings+/profile.two-factor.disable.tsx
@@ -0,0 +1,66 @@
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import { useFetcher } from '@remix-run/react'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireRecentVerification } from '#app/routes/_auth+/verify.server.ts'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { useDoubleCheck } from '#app/utils/misc.tsx'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { type BreadcrumbHandle } from './profile.tsx'
+import { twoFAVerificationType } from './profile.two-factor.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Disable ,
+ getSitemapEntries: () => null,
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ await requireRecentVerification(request)
+ return json({})
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ await requireRecentVerification(request)
+ const userId = await requireUserId(request)
+ await prisma.verification.delete({
+ where: { target_type: { target: userId, type: twoFAVerificationType } },
+ })
+ return redirectWithToast('/settings/profile/two-factor', {
+ title: '2FA Disabled',
+ description: 'Two factor authentication has been disabled.',
+ })
+}
+
+export default function TwoFactorDisableRoute() {
+ const disable2FAFetcher = useFetcher()
+ const dc = useDoubleCheck()
+
+ return (
+
+
+
+ Disabling two factor authentication is not recommended. However, if
+ you would like to do so, click here:
+
+
+ {dc.doubleCheck ? 'Are you sure?' : 'Disable 2FA'}
+
+
+
+ )
+}
diff --git a/app/routes/settings+/profile.two-factor.index.tsx b/app/routes/settings+/profile.two-factor.index.tsx
new file mode 100644
index 0000000..e080dda
--- /dev/null
+++ b/app/routes/settings+/profile.two-factor.index.tsx
@@ -0,0 +1,96 @@
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import { Link, useFetcher, useLoaderData } from '@remix-run/react'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { generateTOTP } from '#app/utils/totp.server.ts'
+import { twoFAVerificationType } from './profile.two-factor.tsx'
+import { twoFAVerifyVerificationType } from './profile.two-factor.verify.tsx'
+
+export const handle: SEOHandle = {
+ getSitemapEntries: () => null,
+}
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const verification = await prisma.verification.findUnique({
+ where: { target_type: { type: twoFAVerificationType, target: userId } },
+ select: { id: true },
+ })
+ return json({ is2FAEnabled: Boolean(verification) })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const { otp: _otp, ...config } = generateTOTP()
+ const verificationData = {
+ ...config,
+ type: twoFAVerifyVerificationType,
+ target: userId,
+ }
+ await prisma.verification.upsert({
+ where: {
+ target_type: { target: userId, type: twoFAVerifyVerificationType },
+ },
+ create: verificationData,
+ update: verificationData,
+ })
+ return redirect('/settings/profile/two-factor/verify')
+}
+
+export default function TwoFactorRoute() {
+ const data = useLoaderData()
+ const enable2FAFetcher = useFetcher()
+
+ return (
+
+ {data.is2FAEnabled ? (
+ <>
+
+
+ You have enabled two-factor authentication.
+
+
+
+
Disable 2FA
+
+ >
+ ) : (
+ <>
+
+
+ You have not enabled two-factor authentication yet.
+
+
+
+ Two factor authentication adds an extra layer of security to your
+ account. You will need to enter a code from an authenticator app
+ like{' '}
+
+ 1Password
+ {' '}
+ to log in.
+
+
+
+ Enable 2FA
+
+
+ >
+ )}
+
+ )
+}
diff --git a/app/routes/settings+/profile.two-factor.tsx b/app/routes/settings+/profile.two-factor.tsx
new file mode 100644
index 0000000..7f5dfd1
--- /dev/null
+++ b/app/routes/settings+/profile.two-factor.tsx
@@ -0,0 +1,16 @@
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import { Outlet } from '@remix-run/react'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { type VerificationTypes } from '#app/routes/_auth+/verify.tsx'
+import { type BreadcrumbHandle } from './profile.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: 2FA ,
+ getSitemapEntries: () => null,
+}
+
+export const twoFAVerificationType = '2fa' satisfies VerificationTypes
+
+export default function TwoFactorRoute() {
+ return
+}
diff --git a/app/routes/settings+/profile.two-factor.verify.tsx b/app/routes/settings+/profile.two-factor.verify.tsx
new file mode 100644
index 0000000..762d8bc
--- /dev/null
+++ b/app/routes/settings+/profile.two-factor.verify.tsx
@@ -0,0 +1,236 @@
+import { getFormProps, getInputProps, useForm } from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type SEOHandle } from '@nasa-gcn/remix-seo'
+import {
+ json,
+ redirect,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import {
+ Form,
+ useActionData,
+ useLoaderData,
+ useNavigation,
+} from '@remix-run/react'
+import * as QRCode from 'qrcode'
+import { z } from 'zod'
+import { ErrorList, OTPField } from '#app/components/forms.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { isCodeValid } from '#app/routes/_auth+/verify.server.ts'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { getDomainUrl, useIsPending } from '#app/utils/misc.tsx'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { getTOTPAuthUri } from '#app/utils/totp.server.ts'
+import { type BreadcrumbHandle } from './profile.tsx'
+import { twoFAVerificationType } from './profile.two-factor.tsx'
+
+export const handle: BreadcrumbHandle & SEOHandle = {
+ breadcrumb: Verify ,
+ getSitemapEntries: () => null,
+}
+
+const CancelSchema = z.object({ intent: z.literal('cancel') })
+const VerifySchema = z.object({
+ intent: z.literal('verify'),
+ code: z.string().min(6).max(6),
+})
+
+const ActionSchema = z.discriminatedUnion('intent', [
+ CancelSchema,
+ VerifySchema,
+])
+
+export const twoFAVerifyVerificationType = '2fa-verify'
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const verification = await prisma.verification.findUnique({
+ where: {
+ target_type: { type: twoFAVerifyVerificationType, target: userId },
+ },
+ select: {
+ id: true,
+ algorithm: true,
+ secret: true,
+ period: true,
+ digits: true,
+ },
+ })
+ if (!verification) {
+ return redirect('/settings/profile/two-factor')
+ }
+ const user = await prisma.user.findUniqueOrThrow({
+ where: { id: userId },
+ select: { email: true },
+ })
+ const issuer = new URL(getDomainUrl(request)).host
+ const otpUri = getTOTPAuthUri({
+ ...verification,
+ accountName: user.email,
+ issuer,
+ })
+ const qrCode = await QRCode.toDataURL(otpUri)
+ return json({ otpUri, qrCode })
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const formData = await request.formData()
+
+ const submission = await parseWithZod(formData, {
+ schema: () =>
+ ActionSchema.superRefine(async (data, ctx) => {
+ if (data.intent === 'cancel') return null
+ const codeIsValid = await isCodeValid({
+ code: data.code,
+ type: twoFAVerifyVerificationType,
+ target: userId,
+ })
+ if (!codeIsValid) {
+ ctx.addIssue({
+ path: ['code'],
+ code: z.ZodIssueCode.custom,
+ message: `Invalid code`,
+ })
+ return z.NEVER
+ }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ switch (submission.value.intent) {
+ case 'cancel': {
+ await prisma.verification.deleteMany({
+ where: { type: twoFAVerifyVerificationType, target: userId },
+ })
+ return redirect('/settings/profile/two-factor')
+ }
+ case 'verify': {
+ await prisma.verification.update({
+ where: {
+ target_type: { type: twoFAVerifyVerificationType, target: userId },
+ },
+ data: { type: twoFAVerificationType },
+ })
+ return redirectWithToast('/settings/profile/two-factor', {
+ type: 'success',
+ title: 'Enabled',
+ description: 'Two-factor authentication has been enabled.',
+ })
+ }
+ }
+}
+
+export default function TwoFactorRoute() {
+ const data = useLoaderData()
+ const actionData = useActionData()
+ const navigation = useNavigation()
+
+ const isPending = useIsPending()
+ const pendingIntent = isPending ? navigation.formData?.get('intent') : null
+
+ const [form, fields] = useForm({
+ id: 'verify-form',
+ constraint: getZodConstraint(ActionSchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: ActionSchema })
+ },
+ })
+ const lastSubmissionIntent = fields.intent.value
+
+ return (
+
+
+
+
Scan this QR code with your authenticator app.
+
+ If you cannot scan the QR code, you can manually add this account to
+ your authenticator app using this code:
+
+
+
+ Once you've added the account, enter the code from your authenticator
+ app below. Once you enable 2FA, you will need to enter a code from
+ your authenticator app every time you log in or perform important
+ actions. Do not lose access to your authenticator app, or you will
+ lose access to your account.
+
+
+
+
+ )
+}
diff --git a/app/routes/users+/$username.test.tsx b/app/routes/users+/$username.test.tsx
new file mode 100644
index 0000000..c9d32dc
--- /dev/null
+++ b/app/routes/users+/$username.test.tsx
@@ -0,0 +1,95 @@
+/**
+ * @vitest-environment jsdom
+ */
+import { faker } from '@faker-js/faker'
+import { createRemixStub } from '@remix-run/testing'
+import { render, screen } from '@testing-library/react'
+import setCookieParser from 'set-cookie-parser'
+import { test } from 'vitest'
+import { loader as rootLoader } from '#app/root.tsx'
+import { getSessionExpirationDate, sessionKey } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { createUser, getUserImages } from '#tests/db-utils.ts'
+import { default as UsernameRoute, loader } from './$username.tsx'
+
+test('The user profile when not logged in as self', async () => {
+ const userImages = await getUserImages()
+ const userImage =
+ userImages[faker.number.int({ min: 0, max: userImages.length - 1 })]
+ const user = await prisma.user.create({
+ select: { id: true, username: true, name: true },
+ data: { ...createUser(), image: { create: userImage } },
+ })
+ const App = createRemixStub([
+ {
+ path: '/users/:username',
+ Component: UsernameRoute,
+ loader,
+ },
+ ])
+
+ const routeUrl = `/users/${user.username}`
+ render( )
+
+ await screen.findByRole('heading', { level: 1, name: user.name! })
+ await screen.findByRole('img', { name: user.name! })
+ await screen.findByRole('link', { name: `${user.name}'s notes` })
+})
+
+test('The user profile when logged in as self', async () => {
+ const userImages = await getUserImages()
+ const userImage =
+ userImages[faker.number.int({ min: 0, max: userImages.length - 1 })]
+ const user = await prisma.user.create({
+ select: { id: true, username: true, name: true },
+ data: { ...createUser(), image: { create: userImage } },
+ })
+ const session = await prisma.session.create({
+ select: { id: true },
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ userId: user.id,
+ },
+ })
+
+ const authSession = await authSessionStorage.getSession()
+ authSession.set(sessionKey, session.id)
+ const setCookieHeader = await authSessionStorage.commitSession(authSession)
+ const parsedCookie = setCookieParser.parseString(setCookieHeader)
+ const cookieHeader = new URLSearchParams({
+ [parsedCookie.name]: parsedCookie.value,
+ }).toString()
+
+ const App = createRemixStub([
+ {
+ id: 'root',
+ path: '/',
+ loader: async (args) => {
+ // add the cookie header to the request
+ args.request.headers.set('cookie', cookieHeader)
+ return rootLoader(args)
+ },
+ children: [
+ {
+ path: 'users/:username',
+ Component: UsernameRoute,
+ loader: async (args) => {
+ // add the cookie header to the request
+ args.request.headers.set('cookie', cookieHeader)
+ return loader(args)
+ },
+ },
+ ],
+ },
+ ])
+
+ const routeUrl = `/users/${user.username}`
+ await render( )
+
+ await screen.findByRole('heading', { level: 1, name: user.name! })
+ await screen.findByRole('img', { name: user.name! })
+ await screen.findByRole('button', { name: /logout/i })
+ await screen.findByRole('link', { name: /my notes/i })
+ await screen.findByRole('link', { name: /edit profile/i })
+})
diff --git a/app/routes/users+/$username.tsx b/app/routes/users+/$username.tsx
new file mode 100644
index 0000000..443133b
--- /dev/null
+++ b/app/routes/users+/$username.tsx
@@ -0,0 +1,122 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { Form, Link, useLoaderData, type MetaFunction } from '@remix-run/react'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { Spacer } from '#app/components/spacer.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { getUserImgSrc } from '#app/utils/misc.tsx'
+import { useOptionalUser } from '#app/utils/user.ts'
+
+export async function loader({ params }: LoaderFunctionArgs) {
+ const user = await prisma.user.findFirst({
+ select: {
+ id: true,
+ name: true,
+ username: true,
+ createdAt: true,
+ image: { select: { id: true } },
+ },
+ where: {
+ username: params.username,
+ },
+ })
+
+ invariantResponse(user, 'User not found', { status: 404 })
+
+ return json({ user, userJoinedDisplay: user.createdAt.toLocaleDateString() })
+}
+
+export default function ProfileRoute() {
+ const data = useLoaderData()
+ const user = data.user
+ const userDisplayName = user.name ?? user.username
+ const loggedInUser = useOptionalUser()
+ const isLoggedInUser = data.user.id === loggedInUser?.id
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{userDisplayName}
+
+
+ Joined {data.userJoinedDisplay}
+
+ {isLoggedInUser ? (
+
+ ) : null}
+
+ {isLoggedInUser ? (
+ <>
+
+
+ My notes
+
+
+
+
+ Edit profile
+
+
+ >
+ ) : (
+
+
+ {userDisplayName}'s notes
+
+
+ )}
+
+
+
+
+ )
+}
+
+export const meta: MetaFunction = ({ data, params }) => {
+ const displayName = data?.user.name ?? params.username
+ return [
+ { title: `${displayName} | Epic Notes` },
+ {
+ name: 'description',
+ content: `Profile of ${displayName} on Epic Notes`,
+ },
+ ]
+}
+
+export function ErrorBoundary() {
+ return (
+ (
+ No user with the username "{params.username}" exists
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/users+/$username_+/__note-editor.server.tsx b/app/routes/users+/$username_+/__note-editor.server.tsx
new file mode 100644
index 0000000..8b1796c
--- /dev/null
+++ b/app/routes/users+/$username_+/__note-editor.server.tsx
@@ -0,0 +1,131 @@
+import { parseWithZod } from '@conform-to/zod'
+import { createId as cuid } from '@paralleldrive/cuid2'
+import {
+ unstable_createMemoryUploadHandler as createMemoryUploadHandler,
+ json,
+ unstable_parseMultipartFormData as parseMultipartFormData,
+ redirect,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import { z } from 'zod'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import {
+ MAX_UPLOAD_SIZE,
+ NoteEditorSchema,
+ type ImageFieldset,
+} from './__note-editor'
+
+function imageHasFile(
+ image: ImageFieldset,
+): image is ImageFieldset & { file: NonNullable } {
+ return Boolean(image.file?.size && image.file?.size > 0)
+}
+
+function imageHasId(
+ image: ImageFieldset,
+): image is ImageFieldset & { id: NonNullable } {
+ return image.id != null
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+
+ const formData = await parseMultipartFormData(
+ request,
+ createMemoryUploadHandler({ maxPartSize: MAX_UPLOAD_SIZE }),
+ )
+
+ const submission = await parseWithZod(formData, {
+ schema: NoteEditorSchema.superRefine(async (data, ctx) => {
+ if (!data.id) return
+
+ const note = await prisma.note.findUnique({
+ select: { id: true },
+ where: { id: data.id, ownerId: userId },
+ })
+ if (!note) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: 'Note not found',
+ })
+ }
+ }).transform(async ({ images = [], ...data }) => {
+ return {
+ ...data,
+ imageUpdates: await Promise.all(
+ images.filter(imageHasId).map(async (i) => {
+ if (imageHasFile(i)) {
+ return {
+ id: i.id,
+ altText: i.altText,
+ contentType: i.file.type,
+ blob: Buffer.from(await i.file.arrayBuffer()),
+ }
+ } else {
+ return {
+ id: i.id,
+ altText: i.altText,
+ }
+ }
+ }),
+ ),
+ newImages: await Promise.all(
+ images
+ .filter(imageHasFile)
+ .filter((i) => !i.id)
+ .map(async (image) => {
+ return {
+ altText: image.altText,
+ contentType: image.file.type,
+ blob: Buffer.from(await image.file.arrayBuffer()),
+ }
+ }),
+ ),
+ }
+ }),
+ async: true,
+ })
+
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const {
+ id: noteId,
+ title,
+ content,
+ imageUpdates = [],
+ newImages = [],
+ } = submission.value
+
+ const updatedNote = await prisma.note.upsert({
+ select: { id: true, owner: { select: { username: true } } },
+ where: { id: noteId ?? '__new_note__' },
+ create: {
+ ownerId: userId,
+ title,
+ content,
+ images: { create: newImages },
+ },
+ update: {
+ title,
+ content,
+ images: {
+ deleteMany: { id: { notIn: imageUpdates.map((i) => i.id) } },
+ updateMany: imageUpdates.map((updates) => ({
+ where: { id: updates.id },
+ data: { ...updates, id: updates.blob ? cuid() : updates.id },
+ })),
+ create: newImages,
+ },
+ },
+ })
+
+ return redirect(
+ `/users/${updatedNote.owner.username}/notes/${updatedNote.id}`,
+ )
+}
diff --git a/app/routes/users+/$username_+/__note-editor.tsx b/app/routes/users+/$username_+/__note-editor.tsx
new file mode 100644
index 0000000..a5ab130
--- /dev/null
+++ b/app/routes/users+/$username_+/__note-editor.tsx
@@ -0,0 +1,271 @@
+import {
+ FormProvider,
+ getFieldsetProps,
+ getFormProps,
+ getInputProps,
+ getTextareaProps,
+ useForm,
+ type FieldMetadata,
+} from '@conform-to/react'
+import { getZodConstraint, parseWithZod } from '@conform-to/zod'
+import { type Note, type NoteImage } from '@prisma/client'
+import { type SerializeFrom } from '@remix-run/node'
+import { Form, useActionData } from '@remix-run/react'
+import { useState } from 'react'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { floatingToolbarClassName } from '#app/components/floating-toolbar.tsx'
+import { ErrorList, Field, TextareaField } from '#app/components/forms.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { Label } from '#app/components/ui/label.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { Textarea } from '#app/components/ui/textarea.tsx'
+import { cn, getNoteImgSrc, useIsPending } from '#app/utils/misc.tsx'
+import { type action } from './__note-editor.server'
+
+const titleMinLength = 1
+const titleMaxLength = 100
+const contentMinLength = 1
+const contentMaxLength = 10000
+
+export const MAX_UPLOAD_SIZE = 1024 * 1024 * 3 // 3MB
+
+const ImageFieldsetSchema = z.object({
+ id: z.string().optional(),
+ file: z
+ .instanceof(File)
+ .optional()
+ .refine((file) => {
+ return !file || file.size <= MAX_UPLOAD_SIZE
+ }, 'File size must be less than 3MB'),
+ altText: z.string().optional(),
+})
+
+export type ImageFieldset = z.infer
+
+export const NoteEditorSchema = z.object({
+ id: z.string().optional(),
+ title: z.string().min(titleMinLength).max(titleMaxLength),
+ content: z.string().min(contentMinLength).max(contentMaxLength),
+ images: z.array(ImageFieldsetSchema).max(5).optional(),
+})
+
+export function NoteEditor({
+ note,
+}: {
+ note?: SerializeFrom<
+ Pick & {
+ images: Array>
+ }
+ >
+}) {
+ const actionData = useActionData()
+ const isPending = useIsPending()
+
+ const [form, fields] = useForm({
+ id: 'note-editor',
+ constraint: getZodConstraint(NoteEditorSchema),
+ lastResult: actionData?.result,
+ onValidate({ formData }) {
+ return parseWithZod(formData, { schema: NoteEditorSchema })
+ },
+ defaultValue: {
+ ...note,
+ images: note?.images ?? [{}],
+ },
+ shouldRevalidate: 'onBlur',
+ })
+ const imageList = fields.images.getFieldList()
+
+ return (
+
+
+
+
+
+ Reset
+
+
+ Submit
+
+
+
+
+ )
+}
+
+function ImageChooser({ meta }: { meta: FieldMetadata }) {
+ const fields = meta.getFieldset()
+ const existingImage = Boolean(fields.id.initialValue)
+ const [previewImage, setPreviewImage] = useState(
+ fields.id.initialValue ? getNoteImgSrc(fields.id.initialValue) : null,
+ )
+ const [altText, setAltText] = useState(fields.altText.initialValue ?? '')
+
+ return (
+
+
+
+
+
+ {previewImage ? (
+
+
+ {existingImage ? null : (
+
+ new
+
+ )}
+
+ ) : (
+
+
+
+ )}
+ {existingImage ? (
+
+ ) : null}
+ {
+ const file = event.target.files?.[0]
+
+ if (file) {
+ const reader = new FileReader()
+ reader.onloadend = () => {
+ setPreviewImage(reader.result as string)
+ }
+ reader.readAsDataURL(file)
+ } else {
+ setPreviewImage(null)
+ }
+ }}
+ accept="image/*"
+ {...getInputProps(fields.file, { type: 'file' })}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return (
+ (
+ No note with the id "{params.noteId}" exists
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/users+/$username_+/notes.$noteId.tsx b/app/routes/users+/$username_+/notes.$noteId.tsx
new file mode 100644
index 0000000..57e0d3e
--- /dev/null
+++ b/app/routes/users+/$username_+/notes.$noteId.tsx
@@ -0,0 +1,221 @@
+import { getFormProps, useForm } from '@conform-to/react'
+import { parseWithZod } from '@conform-to/zod'
+import { invariantResponse } from '@epic-web/invariant'
+import {
+ json,
+ type LoaderFunctionArgs,
+ type ActionFunctionArgs,
+} from '@remix-run/node'
+import {
+ Form,
+ Link,
+ useActionData,
+ useLoaderData,
+ type MetaFunction,
+} from '@remix-run/react'
+import { formatDistanceToNow } from 'date-fns'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { floatingToolbarClassName } from '#app/components/floating-toolbar.tsx'
+import { ErrorList } from '#app/components/forms.tsx'
+import { Button } from '#app/components/ui/button.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { getNoteImgSrc, useIsPending } from '#app/utils/misc.tsx'
+import { requireUserWithPermission } from '#app/utils/permissions.server.ts'
+import { redirectWithToast } from '#app/utils/toast.server.ts'
+import { userHasPermission, useOptionalUser } from '#app/utils/user.ts'
+import { type loader as notesLoader } from './notes.tsx'
+
+export async function loader({ params }: LoaderFunctionArgs) {
+ const note = await prisma.note.findUnique({
+ where: { id: params.noteId },
+ select: {
+ id: true,
+ title: true,
+ content: true,
+ ownerId: true,
+ updatedAt: true,
+ images: {
+ select: {
+ id: true,
+ altText: true,
+ },
+ },
+ },
+ })
+
+ invariantResponse(note, 'Not found', { status: 404 })
+
+ const date = new Date(note.updatedAt)
+ const timeAgo = formatDistanceToNow(date)
+
+ return json({
+ note,
+ timeAgo,
+ })
+}
+
+const DeleteFormSchema = z.object({
+ intent: z.literal('delete-note'),
+ noteId: z.string(),
+})
+
+export async function action({ request }: ActionFunctionArgs) {
+ const userId = await requireUserId(request)
+ const formData = await request.formData()
+ const submission = parseWithZod(formData, {
+ schema: DeleteFormSchema,
+ })
+ if (submission.status !== 'success') {
+ return json(
+ { result: submission.reply() },
+ { status: submission.status === 'error' ? 400 : 200 },
+ )
+ }
+
+ const { noteId } = submission.value
+
+ const note = await prisma.note.findFirst({
+ select: { id: true, ownerId: true, owner: { select: { username: true } } },
+ where: { id: noteId },
+ })
+ invariantResponse(note, 'Not found', { status: 404 })
+
+ const isOwner = note.ownerId === userId
+ await requireUserWithPermission(
+ request,
+ isOwner ? `delete:note:own` : `delete:note:any`,
+ )
+
+ await prisma.note.delete({ where: { id: note.id } })
+
+ return redirectWithToast(`/users/${note.owner.username}/notes`, {
+ type: 'success',
+ title: 'Success',
+ description: 'Your note has been deleted.',
+ })
+}
+
+export default function NoteRoute() {
+ const data = useLoaderData()
+ const user = useOptionalUser()
+ const isOwner = user?.id === data.note.ownerId
+ const canDelete = userHasPermission(
+ user,
+ isOwner ? `delete:note:own` : `delete:note:any`,
+ )
+ const displayBar = canDelete || isOwner
+
+ return (
+
+
{data.note.title}
+
+
+ {data.note.images.map((image) => (
+
+
+
+
+
+ ))}
+
+
+ {data.note.content}
+
+
+ {displayBar ? (
+
+
+
+ {data.timeAgo} ago
+
+
+
+ {canDelete ? : null}
+
+
+
+ Edit
+
+
+
+
+
+ ) : null}
+
+ )
+}
+
+export function DeleteNote({ id }: { id: string }) {
+ const actionData = useActionData()
+ const isPending = useIsPending()
+ const [form] = useForm({
+ id: 'delete-note',
+ lastResult: actionData?.result,
+ })
+
+ return (
+
+ )
+}
+
+export const meta: MetaFunction<
+ typeof loader,
+ { 'routes/users+/$username_+/notes': typeof notesLoader }
+> = ({ data, params, matches }) => {
+ const notesMatch = matches.find(
+ (m) => m.id === 'routes/users+/$username_+/notes',
+ )
+ const displayName = notesMatch?.data?.owner.name ?? params.username
+ const noteTitle = data?.note.title ?? 'Note'
+ const noteContentsSummary =
+ data && data.note.content.length > 100
+ ? data?.note.content.slice(0, 97) + '...'
+ : 'No content'
+ return [
+ { title: `${noteTitle} | ${displayName}'s Notes | Epic Notes` },
+ {
+ name: 'description',
+ content: noteContentsSummary,
+ },
+ ]
+}
+
+export function ErrorBoundary() {
+ return (
+ You are not allowed to do that
,
+ 404: ({ params }) => (
+ No note with the id "{params.noteId}" exists
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/users+/$username_+/notes.$noteId_.edit.tsx b/app/routes/users+/$username_+/notes.$noteId_.edit.tsx
new file mode 100644
index 0000000..0d14817
--- /dev/null
+++ b/app/routes/users+/$username_+/notes.$noteId_.edit.tsx
@@ -0,0 +1,50 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { useLoaderData } from '@remix-run/react'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { NoteEditor } from './__note-editor.tsx'
+
+export { action } from './__note-editor.server.tsx'
+
+export async function loader({ params, request }: LoaderFunctionArgs) {
+ const userId = await requireUserId(request)
+ const note = await prisma.note.findFirst({
+ select: {
+ id: true,
+ title: true,
+ content: true,
+ images: {
+ select: {
+ id: true,
+ altText: true,
+ },
+ },
+ },
+ where: {
+ id: params.noteId,
+ ownerId: userId,
+ },
+ })
+ invariantResponse(note, 'Not found', { status: 404 })
+ return json({ note: note })
+}
+
+export default function NoteEdit() {
+ const data = useLoaderData()
+
+ return
+}
+
+export function ErrorBoundary() {
+ return (
+ (
+ No note with the id "{params.noteId}" exists
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/users+/$username_+/notes.index.tsx b/app/routes/users+/$username_+/notes.index.tsx
new file mode 100644
index 0000000..ab05941
--- /dev/null
+++ b/app/routes/users+/$username_+/notes.index.tsx
@@ -0,0 +1,29 @@
+import { type MetaFunction } from '@remix-run/react'
+import { type loader as notesLoader } from './notes.tsx'
+
+export default function NotesIndexRoute() {
+ return (
+
+ )
+}
+
+export const meta: MetaFunction<
+ null,
+ { 'routes/users+/$username_+/notes': typeof notesLoader }
+> = ({ params, matches }) => {
+ const notesMatch = matches.find(
+ (m) => m.id === 'routes/users+/$username_+/notes',
+ )
+ const displayName = notesMatch?.data?.owner.name ?? params.username
+ const noteCount = notesMatch?.data?.owner.notes.length ?? 0
+ const notesText = noteCount === 1 ? 'note' : 'notes'
+ return [
+ { title: `${displayName}'s Notes | Epic Notes` },
+ {
+ name: 'description',
+ content: `Checkout ${displayName}'s ${noteCount} ${notesText} on Epic Notes`,
+ },
+ ]
+}
diff --git a/app/routes/users+/$username_+/notes.new.tsx b/app/routes/users+/$username_+/notes.new.tsx
new file mode 100644
index 0000000..ecc8580
--- /dev/null
+++ b/app/routes/users+/$username_+/notes.new.tsx
@@ -0,0 +1,12 @@
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { requireUserId } from '#app/utils/auth.server.ts'
+import { NoteEditor } from './__note-editor.tsx'
+
+export { action } from './__note-editor.server.tsx'
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ await requireUserId(request)
+ return json({})
+}
+
+export default NoteEditor
diff --git a/app/routes/users+/$username_+/notes.tsx b/app/routes/users+/$username_+/notes.tsx
new file mode 100644
index 0000000..58134a3
--- /dev/null
+++ b/app/routes/users+/$username_+/notes.tsx
@@ -0,0 +1,100 @@
+import { invariantResponse } from '@epic-web/invariant'
+import { json, type LoaderFunctionArgs } from '@remix-run/node'
+import { Link, NavLink, Outlet, useLoaderData } from '@remix-run/react'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { cn, getUserImgSrc } from '#app/utils/misc.tsx'
+import { useOptionalUser } from '#app/utils/user.ts'
+
+export async function loader({ params }: LoaderFunctionArgs) {
+ const owner = await prisma.user.findFirst({
+ select: {
+ id: true,
+ name: true,
+ username: true,
+ image: { select: { id: true } },
+ notes: { select: { id: true, title: true } },
+ },
+ where: { username: params.username },
+ })
+
+ invariantResponse(owner, 'Owner not found', { status: 404 })
+
+ return json({ owner })
+}
+
+export default function NotesRoute() {
+ const data = useLoaderData()
+ const user = useOptionalUser()
+ const isOwner = user?.id === data.owner.id
+ const ownerDisplayName = data.owner.name ?? data.owner.username
+ const navLinkDefaultClassName =
+ 'line-clamp-2 block rounded-l-full py-2 pl-8 pr-6 text-base lg:text-xl'
+ return (
+
+
+
+
+
+
+
+ {ownerDisplayName}'s Notes
+
+
+
+ {isOwner ? (
+
+
+ cn(navLinkDefaultClassName, isActive && 'bg-accent')
+ }
+ >
+ New Note
+
+
+ ) : null}
+ {data.owner.notes.map((note) => (
+
+
+ cn(navLinkDefaultClassName, isActive && 'bg-accent')
+ }
+ >
+ {note.title}
+
+
+ ))}
+
+
+
+
+
+
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return (
+ (
+ No user with the username "{params.username}" exists
+ ),
+ }}
+ />
+ )
+}
diff --git a/app/routes/users+/index.tsx b/app/routes/users+/index.tsx
new file mode 100644
index 0000000..c070332
--- /dev/null
+++ b/app/routes/users+/index.tsx
@@ -0,0 +1,113 @@
+import { json, redirect, type LoaderFunctionArgs } from '@remix-run/node'
+import { Link, useLoaderData } from '@remix-run/react'
+import { z } from 'zod'
+import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx'
+import { ErrorList } from '#app/components/forms.tsx'
+import { SearchBar } from '#app/components/search-bar.tsx'
+import { prisma } from '#app/utils/db.server.ts'
+import { cn, getUserImgSrc, useDelayedIsPending } from '#app/utils/misc.tsx'
+
+const UserSearchResultSchema = z.object({
+ id: z.string(),
+ username: z.string(),
+ name: z.string().nullable(),
+ imageId: z.string().nullable(),
+})
+
+const UserSearchResultsSchema = z.array(UserSearchResultSchema)
+
+export async function loader({ request }: LoaderFunctionArgs) {
+ const searchTerm = new URL(request.url).searchParams.get('search')
+ if (searchTerm === '') {
+ return redirect('/users')
+ }
+
+ const like = `%${searchTerm ?? ''}%`
+ const rawUsers = await prisma.$queryRaw`
+ SELECT User.id, User.username, User.name, UserImage.id AS imageId
+ FROM User
+ LEFT JOIN UserImage ON User.id = UserImage.userId
+ WHERE User.username LIKE ${like}
+ OR User.name LIKE ${like}
+ ORDER BY (
+ SELECT Note.updatedAt
+ FROM Note
+ WHERE Note.ownerId = User.id
+ ORDER BY Note.updatedAt DESC
+ LIMIT 1
+ ) DESC
+ LIMIT 50
+ `
+
+ const result = UserSearchResultsSchema.safeParse(rawUsers)
+ if (!result.success) {
+ return json({ status: 'error', error: result.error.message } as const, {
+ status: 400,
+ })
+ }
+ return json({ status: 'idle', users: result.data } as const)
+}
+
+export default function UsersRoute() {
+ const data = useLoaderData()
+ const isPending = useDelayedIsPending({
+ formMethod: 'GET',
+ formAction: '/users',
+ })
+
+ if (data.status === 'error') {
+ console.error(data.error)
+ }
+
+ return (
+
+
Epic Notes Users
+
+
+
+
+ {data.status === 'idle' ? (
+ data.users.length ? (
+
+ {data.users.map((user) => (
+
+
+
+ {user.name ? (
+
+ {user.name}
+
+ ) : null}
+
+ {user.username}
+
+
+
+ ))}
+
+ ) : (
+ No users found
+ )
+ ) : data.status === 'error' ? (
+
+ ) : null}
+
+
+ )
+}
+
+export function ErrorBoundary() {
+ return
+}
diff --git a/app/styles/tailwind.css b/app/styles/tailwind.css
new file mode 100644
index 0000000..bc9460f
--- /dev/null
+++ b/app/styles/tailwind.css
@@ -0,0 +1,80 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ /* --font-sans: here if you have one */
+ /* --font-mono: here if you got it... */
+
+ /* prefixed with foreground because it should look good on the background */
+ --foreground-destructive: 345 82.7% 40.8%;
+
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --muted: 210 40% 93%;
+ --muted-foreground: 215.4 16.3% 30%;
+
+ --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%;
+ --input-invalid: 0 84.2% 60.2%;
+
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 20% 83%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --accent: 210 40% 90%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 70% 50%;
+ --destructive-foreground: 210 40% 98%;
+
+ --ring: 215 20.2% 65.1%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ /* prefixed with foreground because it should look good on the background */
+ --foreground-destructive: -4 84% 60%;
+
+ --muted: 217.2 32.6% 12%;
+ --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%;
+ --input-invalid: 0 62.8% 30.6%;
+
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 20% 24%;
+ --secondary-foreground: 210 40% 98%;
+
+ --accent: 217.2 32.6% 10%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 60% 40%;
+ --destructive-foreground: 0 85.7% 97.3%;
+
+ --ring: 217.2 32.6% 60%;
+ }
+}
diff --git a/app/utils/auth.server.ts b/app/utils/auth.server.ts
new file mode 100644
index 0000000..5758746
--- /dev/null
+++ b/app/utils/auth.server.ts
@@ -0,0 +1,240 @@
+import { type Connection, type Password, type User } from '@prisma/client'
+import { redirect } from '@remix-run/node'
+import bcrypt from 'bcryptjs'
+import { Authenticator } from 'remix-auth'
+import { safeRedirect } from 'remix-utils/safe-redirect'
+import { connectionSessionStorage, providers } from './connections.server.ts'
+import { prisma } from './db.server.ts'
+import { combineHeaders, downloadFile } from './misc.tsx'
+import { type ProviderUser } from './providers/provider.ts'
+import { authSessionStorage } from './session.server.ts'
+
+export const SESSION_EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30
+export const getSessionExpirationDate = () =>
+ new Date(Date.now() + SESSION_EXPIRATION_TIME)
+
+export const sessionKey = 'sessionId'
+
+export const authenticator = new Authenticator(
+ connectionSessionStorage,
+)
+
+for (const [providerName, provider] of Object.entries(providers)) {
+ authenticator.use(provider.getAuthStrategy(), providerName)
+}
+
+export async function getUserId(request: Request) {
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const sessionId = authSession.get(sessionKey)
+ if (!sessionId) return null
+ const session = await prisma.session.findUnique({
+ select: { user: { select: { id: true } } },
+ where: { id: sessionId, expirationDate: { gt: new Date() } },
+ })
+ if (!session?.user) {
+ throw redirect('/', {
+ headers: {
+ 'set-cookie': await authSessionStorage.destroySession(authSession),
+ },
+ })
+ }
+ return session.user.id
+}
+
+export async function requireUserId(
+ request: Request,
+ { redirectTo }: { redirectTo?: string | null } = {},
+) {
+ const userId = await getUserId(request)
+ if (!userId) {
+ const requestUrl = new URL(request.url)
+ redirectTo =
+ redirectTo === null
+ ? null
+ : (redirectTo ?? `${requestUrl.pathname}${requestUrl.search}`)
+ const loginParams = redirectTo ? new URLSearchParams({ redirectTo }) : null
+ const loginRedirect = ['/login', loginParams?.toString()]
+ .filter(Boolean)
+ .join('?')
+ throw redirect(loginRedirect)
+ }
+ return userId
+}
+
+export async function requireAnonymous(request: Request) {
+ const userId = await getUserId(request)
+ if (userId) {
+ throw redirect('/')
+ }
+}
+
+export async function login({
+ username,
+ password,
+}: {
+ username: User['username']
+ password: string
+}) {
+ const user = await verifyUserPassword({ username }, password)
+ if (!user) return null
+ const session = await prisma.session.create({
+ select: { id: true, expirationDate: true, userId: true },
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ userId: user.id,
+ },
+ })
+ return session
+}
+
+export async function resetUserPassword({
+ username,
+ password,
+}: {
+ username: User['username']
+ password: string
+}) {
+ const hashedPassword = await getPasswordHash(password)
+ return prisma.user.update({
+ where: { username },
+ data: {
+ password: {
+ update: {
+ hash: hashedPassword,
+ },
+ },
+ },
+ })
+}
+
+export async function signup({
+ email,
+ username,
+ password,
+ name,
+}: {
+ email: User['email']
+ username: User['username']
+ name: User['name']
+ password: string
+}) {
+ const hashedPassword = await getPasswordHash(password)
+
+ const session = await prisma.session.create({
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ user: {
+ create: {
+ email: email.toLowerCase(),
+ username: username.toLowerCase(),
+ name,
+ roles: { connect: { name: 'user' } },
+ password: {
+ create: {
+ hash: hashedPassword,
+ },
+ },
+ },
+ },
+ },
+ select: { id: true, expirationDate: true },
+ })
+
+ return session
+}
+
+export async function signupWithConnection({
+ email,
+ username,
+ name,
+ providerId,
+ providerName,
+ imageUrl,
+}: {
+ email: User['email']
+ username: User['username']
+ name: User['name']
+ providerId: Connection['providerId']
+ providerName: Connection['providerName']
+ imageUrl?: string
+}) {
+ const session = await prisma.session.create({
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ user: {
+ create: {
+ email: email.toLowerCase(),
+ username: username.toLowerCase(),
+ name,
+ roles: { connect: { name: 'user' } },
+ connections: { create: { providerId, providerName } },
+ image: imageUrl
+ ? { create: await downloadFile(imageUrl) }
+ : undefined,
+ },
+ },
+ },
+ select: { id: true, expirationDate: true },
+ })
+
+ return session
+}
+
+export async function logout(
+ {
+ request,
+ redirectTo = '/',
+ }: {
+ request: Request
+ redirectTo?: string
+ },
+ responseInit?: ResponseInit,
+) {
+ const authSession = await authSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const sessionId = authSession.get(sessionKey)
+ // if this fails, we still need to delete the session from the user's browser
+ // and it doesn't do any harm staying in the db anyway.
+ if (sessionId) {
+ // the .catch is important because that's what triggers the query.
+ // learn more about PrismaPromise: https://www.prisma.io/docs/orm/reference/prisma-client-reference#prismapromise-behavior
+ void prisma.session.deleteMany({ where: { id: sessionId } }).catch(() => {})
+ }
+ throw redirect(safeRedirect(redirectTo), {
+ ...responseInit,
+ headers: combineHeaders(
+ { 'set-cookie': await authSessionStorage.destroySession(authSession) },
+ responseInit?.headers,
+ ),
+ })
+}
+
+export async function getPasswordHash(password: string) {
+ const hash = await bcrypt.hash(password, 10)
+ return hash
+}
+
+export async function verifyUserPassword(
+ where: Pick | Pick,
+ password: Password['hash'],
+) {
+ const userWithPassword = await prisma.user.findUnique({
+ where,
+ select: { id: true, password: { select: { hash: true } } },
+ })
+
+ if (!userWithPassword || !userWithPassword.password) {
+ return null
+ }
+
+ const isValid = await bcrypt.compare(password, userWithPassword.password.hash)
+
+ if (!isValid) {
+ return null
+ }
+
+ return { id: userWithPassword.id }
+}
diff --git a/app/utils/cache.server.ts b/app/utils/cache.server.ts
new file mode 100644
index 0000000..618f5a0
--- /dev/null
+++ b/app/utils/cache.server.ts
@@ -0,0 +1,182 @@
+import fs from 'node:fs'
+import {
+ cachified as baseCachified,
+ verboseReporter,
+ mergeReporters,
+ type CacheEntry,
+ type Cache as CachifiedCache,
+ type CachifiedOptions,
+ type Cache,
+ totalTtl,
+ type CreateReporter,
+} from '@epic-web/cachified'
+import { remember } from '@epic-web/remember'
+import Database from 'better-sqlite3'
+import { LRUCache } from 'lru-cache'
+import { z } from 'zod'
+import { updatePrimaryCacheValue } from '#app/routes/admin+/cache_.sqlite.server.ts'
+import { getInstanceInfo, getInstanceInfoSync } from './litefs.server.ts'
+import { cachifiedTimingReporter, type Timings } from './timing.server.ts'
+
+const CACHE_DATABASE_PATH = process.env.CACHE_DATABASE_PATH
+
+const cacheDb = remember('cacheDb', createDatabase)
+
+function createDatabase(tryAgain = true): Database.Database {
+ const db = new Database(CACHE_DATABASE_PATH)
+ const { currentIsPrimary } = getInstanceInfoSync()
+ if (!currentIsPrimary) return db
+
+ try {
+ // create cache table with metadata JSON column and value JSON column if it does not exist already
+ db.exec(`
+ CREATE TABLE IF NOT EXISTS cache (
+ key TEXT PRIMARY KEY,
+ metadata TEXT,
+ value TEXT
+ )
+ `)
+ } catch (error: unknown) {
+ fs.unlinkSync(CACHE_DATABASE_PATH)
+ if (tryAgain) {
+ console.error(
+ `Error creating cache database, deleting the file at "${CACHE_DATABASE_PATH}" and trying again...`,
+ )
+ return createDatabase(false)
+ }
+ throw error
+ }
+ return db
+}
+
+const lru = remember(
+ 'lru-cache',
+ () => new LRUCache>({ max: 5000 }),
+)
+
+export const lruCache = {
+ name: 'app-memory-cache',
+ set: (key, value) => {
+ const ttl = totalTtl(value?.metadata)
+ lru.set(key, value, {
+ ttl: ttl === Infinity ? undefined : ttl,
+ start: value?.metadata?.createdTime,
+ })
+ return value
+ },
+ get: (key) => lru.get(key),
+ delete: (key) => lru.delete(key),
+} satisfies Cache
+
+const cacheEntrySchema = z.object({
+ metadata: z.object({
+ createdTime: z.number(),
+ ttl: z.number().nullable().optional(),
+ swr: z.number().nullable().optional(),
+ }),
+ value: z.unknown(),
+})
+const cacheQueryResultSchema = z.object({
+ metadata: z.string(),
+ value: z.string(),
+})
+
+export const cache: CachifiedCache = {
+ name: 'SQLite cache',
+ get(key) {
+ const result = cacheDb
+ .prepare('SELECT value, metadata FROM cache WHERE key = ?')
+ .get(key)
+ const parseResult = cacheQueryResultSchema.safeParse(result)
+ if (!parseResult.success) return null
+
+ const parsedEntry = cacheEntrySchema.safeParse({
+ metadata: JSON.parse(parseResult.data.metadata),
+ value: JSON.parse(parseResult.data.value),
+ })
+ if (!parsedEntry.success) return null
+ const { metadata, value } = parsedEntry.data
+ if (!value) return null
+ return { metadata, value }
+ },
+ async set(key, entry) {
+ const { currentIsPrimary, primaryInstance } = await getInstanceInfo()
+ if (currentIsPrimary) {
+ cacheDb
+ .prepare(
+ 'INSERT OR REPLACE INTO cache (key, value, metadata) VALUES (@key, @value, @metadata)',
+ )
+ .run({
+ key,
+ value: JSON.stringify(entry.value),
+ metadata: JSON.stringify(entry.metadata),
+ })
+ } else {
+ // fire-and-forget cache update
+ void updatePrimaryCacheValue({
+ key,
+ cacheValue: entry,
+ }).then((response) => {
+ if (!response.ok) {
+ console.error(
+ `Error updating cache value for key "${key}" on primary instance (${primaryInstance}): ${response.status} ${response.statusText}`,
+ { entry },
+ )
+ }
+ })
+ }
+ },
+ async delete(key) {
+ const { currentIsPrimary, primaryInstance } = await getInstanceInfo()
+ if (currentIsPrimary) {
+ cacheDb.prepare('DELETE FROM cache WHERE key = ?').run(key)
+ } else {
+ // fire-and-forget cache update
+ void updatePrimaryCacheValue({
+ key,
+ cacheValue: undefined,
+ }).then((response) => {
+ if (!response.ok) {
+ console.error(
+ `Error deleting cache value for key "${key}" on primary instance (${primaryInstance}): ${response.status} ${response.statusText}`,
+ )
+ }
+ })
+ }
+ },
+}
+
+export async function getAllCacheKeys(limit: number) {
+ return {
+ sqlite: cacheDb
+ .prepare('SELECT key FROM cache LIMIT ?')
+ .all(limit)
+ .map((row) => (row as { key: string }).key),
+ lru: [...lru.keys()],
+ }
+}
+
+export async function searchCacheKeys(search: string, limit: number) {
+ return {
+ sqlite: cacheDb
+ .prepare('SELECT key FROM cache WHERE key LIKE ? LIMIT ?')
+ .all(`%${search}%`, limit)
+ .map((row) => (row as { key: string }).key),
+ lru: [...lru.keys()].filter((key) => key.includes(search)),
+ }
+}
+
+export async function cachified(
+ {
+ timings,
+ ...options
+ }: CachifiedOptions & {
+ timings?: Timings
+ },
+ reporter: CreateReporter = verboseReporter(),
+): Promise {
+ return baseCachified(
+ options,
+ mergeReporters(cachifiedTimingReporter(timings), reporter),
+ )
+}
diff --git a/app/utils/client-hints.tsx b/app/utils/client-hints.tsx
new file mode 100644
index 0000000..546dfd2
--- /dev/null
+++ b/app/utils/client-hints.tsx
@@ -0,0 +1,51 @@
+/**
+ * This file contains utilities for using client hints for user preference which
+ * are needed by the server, but are only known by the browser.
+ */
+import { getHintUtils } from '@epic-web/client-hints'
+import {
+ clientHint as colorSchemeHint,
+ subscribeToSchemeChange,
+} from '@epic-web/client-hints/color-scheme'
+import { clientHint as timeZoneHint } from '@epic-web/client-hints/time-zone'
+import { useRevalidator } from '@remix-run/react'
+import * as React from 'react'
+import { useRequestInfo } from './request-info.ts'
+
+const hintsUtils = getHintUtils({
+ theme: colorSchemeHint,
+ timeZone: timeZoneHint,
+ // add other hints here
+})
+
+export const { getHints } = hintsUtils
+
+/**
+ * @returns an object with the client hints and their values
+ */
+export function useHints() {
+ const requestInfo = useRequestInfo()
+ return requestInfo.hints
+}
+
+/**
+ * @returns inline script element that checks for client hints and sets cookies
+ * if they are not set then reloads the page if any cookie was set to an
+ * inaccurate value.
+ */
+export function ClientHintCheck({ nonce }: { nonce: string }) {
+ const { revalidate } = useRevalidator()
+ React.useEffect(
+ () => subscribeToSchemeChange(() => revalidate()),
+ [revalidate],
+ )
+
+ return (
+
+ )
+}
diff --git a/app/utils/connections.server.ts b/app/utils/connections.server.ts
new file mode 100644
index 0000000..524c5fa
--- /dev/null
+++ b/app/utils/connections.server.ts
@@ -0,0 +1,33 @@
+import { createCookieSessionStorage } from '@remix-run/node'
+import { type ProviderName } from './connections.tsx'
+import { GitHubProvider } from './providers/github.server.ts'
+import { type AuthProvider } from './providers/provider.ts'
+import { type Timings } from './timing.server.ts'
+
+export const connectionSessionStorage = createCookieSessionStorage({
+ cookie: {
+ name: 'en_connection',
+ sameSite: 'lax', // CSRF protection is advised if changing to 'none'
+ path: '/',
+ httpOnly: true,
+ maxAge: 60 * 10, // 10 minutes
+ secrets: process.env.SESSION_SECRET.split(','),
+ secure: process.env.NODE_ENV === 'production',
+ },
+})
+
+export const providers: Record = {
+ github: new GitHubProvider(),
+}
+
+export function handleMockAction(providerName: ProviderName, request: Request) {
+ return providers[providerName].handleMockAction(request)
+}
+
+export function resolveConnectionData(
+ providerName: ProviderName,
+ providerId: string,
+ options?: { timings?: Timings },
+) {
+ return providers[providerName].resolveConnectionData(providerId, options)
+}
diff --git a/app/utils/connections.tsx b/app/utils/connections.tsx
new file mode 100644
index 0000000..39fd69b
--- /dev/null
+++ b/app/utils/connections.tsx
@@ -0,0 +1,57 @@
+import { Form } from '@remix-run/react'
+import { z } from 'zod'
+import { Icon } from '#app/components/ui/icon.tsx'
+import { StatusButton } from '#app/components/ui/status-button.tsx'
+import { useIsPending } from './misc.tsx'
+
+export const GITHUB_PROVIDER_NAME = 'github'
+// to add another provider, set their name here and add it to the providerNames below
+
+export const providerNames = [GITHUB_PROVIDER_NAME] as const
+export const ProviderNameSchema = z.enum(providerNames)
+export type ProviderName = z.infer
+
+export const providerLabels: Record = {
+ [GITHUB_PROVIDER_NAME]: 'GitHub',
+} as const
+
+export const providerIcons: Record = {
+ [GITHUB_PROVIDER_NAME]: ,
+} as const
+
+export function ProviderConnectionForm({
+ redirectTo,
+ type,
+ providerName,
+}: {
+ redirectTo?: string | null
+ type: 'Connect' | 'Login' | 'Signup'
+ providerName: ProviderName
+}) {
+ const label = providerLabels[providerName]
+ const formAction = `/auth/${providerName}`
+ const isPending = useIsPending({ formAction })
+ return (
+
+ )
+}
diff --git a/app/utils/db.server.ts b/app/utils/db.server.ts
new file mode 100644
index 0000000..9e010e8
--- /dev/null
+++ b/app/utils/db.server.ts
@@ -0,0 +1,36 @@
+import { remember } from '@epic-web/remember'
+import { PrismaClient } from '@prisma/client'
+import chalk from 'chalk'
+
+export const prisma = remember('prisma', () => {
+ // NOTE: if you change anything in this function you'll need to restart
+ // the dev server to see your changes.
+
+ // Feel free to change this log threshold to something that makes sense for you
+ const logThreshold = 20
+
+ const client = new PrismaClient({
+ log: [
+ { level: 'query', emit: 'event' },
+ { level: 'error', emit: 'stdout' },
+ { level: 'warn', emit: 'stdout' },
+ ],
+ })
+ client.$on('query', async (e) => {
+ if (e.duration < logThreshold) return
+ const color =
+ e.duration < logThreshold * 1.1
+ ? 'green'
+ : e.duration < logThreshold * 1.2
+ ? 'blue'
+ : e.duration < logThreshold * 1.3
+ ? 'yellow'
+ : e.duration < logThreshold * 1.4
+ ? 'redBright'
+ : 'red'
+ const dur = chalk[color](`${e.duration}ms`)
+ console.info(`prisma:query - ${dur} - ${e.query}`)
+ })
+ void client.$connect()
+ return client
+})
diff --git a/app/utils/email.server.ts b/app/utils/email.server.ts
new file mode 100644
index 0000000..f62a369
--- /dev/null
+++ b/app/utils/email.server.ts
@@ -0,0 +1,98 @@
+import { renderAsync } from '@react-email/components'
+import { type ReactElement } from 'react'
+import { z } from 'zod'
+
+const resendErrorSchema = z.union([
+ z.object({
+ name: z.string(),
+ message: z.string(),
+ statusCode: z.number(),
+ }),
+ z.object({
+ name: z.literal('UnknownError'),
+ message: z.literal('Unknown Error'),
+ statusCode: z.literal(500),
+ cause: z.any(),
+ }),
+])
+type ResendError = z.infer
+
+const resendSuccessSchema = z.object({
+ id: z.string(),
+})
+
+export async function sendEmail({
+ react,
+ ...options
+}: {
+ to: string
+ subject: string
+} & (
+ | { html: string; text: string; react?: never }
+ | { react: ReactElement; html?: never; text?: never }
+)) {
+ const from = 'hello@epicstack.dev'
+
+ const email = {
+ from,
+ ...options,
+ ...(react ? await renderReactEmail(react) : null),
+ }
+
+ // feel free to remove this condition once you've set up resend
+ if (!process.env.RESEND_API_KEY && !process.env.MOCKS) {
+ console.error(`RESEND_API_KEY not set and we're not in mocks mode.`)
+ console.error(
+ `To send emails, set the RESEND_API_KEY environment variable.`,
+ )
+ console.error(`Would have sent the following email:`, JSON.stringify(email))
+ return {
+ status: 'success',
+ data: { id: 'mocked' },
+ } as const
+ }
+
+ const response = await fetch('https://api.resend.com/emails', {
+ method: 'POST',
+ body: JSON.stringify(email),
+ headers: {
+ Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
+ 'Content-Type': 'application/json',
+ },
+ })
+ const data = await response.json()
+ const parsedData = resendSuccessSchema.safeParse(data)
+
+ if (response.ok && parsedData.success) {
+ return {
+ status: 'success',
+ data: parsedData,
+ } as const
+ } else {
+ const parseResult = resendErrorSchema.safeParse(data)
+ if (parseResult.success) {
+ return {
+ status: 'error',
+ error: parseResult.data,
+ } as const
+ } else {
+ return {
+ status: 'error',
+ error: {
+ name: 'UnknownError',
+ message: 'Unknown Error',
+ statusCode: 500,
+ cause: data,
+ } satisfies ResendError,
+ } as const
+ }
+ }
+}
+
+async function renderReactEmail(react: ReactElement) {
+ const [html, text] = await Promise.all([
+ renderAsync(react),
+ renderAsync(react, { plainText: true }),
+ ])
+ return { html, text }
+}
diff --git a/app/utils/env.server.ts b/app/utils/env.server.ts
new file mode 100644
index 0000000..e59eb46
--- /dev/null
+++ b/app/utils/env.server.ts
@@ -0,0 +1,65 @@
+import { z } from 'zod'
+
+const schema = z.object({
+ NODE_ENV: z.enum(['production', 'development', 'test'] as const),
+ DATABASE_PATH: z.string(),
+ DATABASE_URL: z.string(),
+ SESSION_SECRET: z.string(),
+ INTERNAL_COMMAND_TOKEN: z.string(),
+ HONEYPOT_SECRET: z.string(),
+ CACHE_DATABASE_PATH: z.string(),
+ // If you plan on using Sentry, uncomment this line
+ // SENTRY_DSN: z.string(),
+ // If you plan to use Resend, uncomment this line
+ // RESEND_API_KEY: z.string(),
+ // If you plan to use GitHub auth, remove the default:
+ GITHUB_CLIENT_ID: z.string().default('MOCK_GITHUB_CLIENT_ID'),
+ GITHUB_CLIENT_SECRET: z.string().default('MOCK_GITHUB_CLIENT_SECRET'),
+ GITHUB_TOKEN: z.string().default('MOCK_GITHUB_TOKEN'),
+ ALLOW_INDEXING: z.enum(['true', 'false']).optional(),
+})
+
+declare global {
+ namespace NodeJS {
+ interface ProcessEnv extends z.infer {}
+ }
+}
+
+export function init() {
+ const parsed = schema.safeParse(process.env)
+
+ if (parsed.success === false) {
+ console.error(
+ 'â Invalid environment variables:',
+ parsed.error.flatten().fieldErrors,
+ )
+
+ throw new Error('Invalid environment variables')
+ }
+}
+
+/**
+ * This is used in both `entry.server.ts` and `root.tsx` to ensure that
+ * the environment variables are set and globally available before the app is
+ * started.
+ *
+ * NOTE: Do *not* add any environment variables in here that you do not wish to
+ * be included in the client.
+ * @returns all public ENV variables
+ */
+export function getEnv() {
+ return {
+ MODE: process.env.NODE_ENV,
+ SENTRY_DSN: process.env.SENTRY_DSN,
+ ALLOW_INDEXING: process.env.ALLOW_INDEXING,
+ }
+}
+
+type ENV = ReturnType
+
+declare global {
+ var ENV: ENV
+ interface Window {
+ ENV: ENV
+ }
+}
diff --git a/app/utils/extended-theme.ts b/app/utils/extended-theme.ts
new file mode 100644
index 0000000..d2ec3f1
--- /dev/null
+++ b/app/utils/extended-theme.ts
@@ -0,0 +1,102 @@
+import { type Config } from 'tailwindcss'
+
+export const extendedTheme = {
+ colors: {
+ border: 'hsl(var(--border))',
+ input: {
+ DEFAULT: 'hsl(var(--input))',
+ invalid: 'hsl(var(--input-invalid))',
+ },
+ ring: {
+ DEFAULT: 'hsl(var(--ring))',
+ invalid: 'hsl(var(--foreground-destructive))',
+ },
+ background: 'hsl(var(--background))',
+ foreground: {
+ DEFAULT: 'hsl(var(--foreground))',
+ destructive: 'hsl(var(--foreground-destructive))',
+ },
+ 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))',
+ },
+ },
+ borderColor: {
+ DEFAULT: 'hsl(var(--border))',
+ },
+ borderRadius: {
+ lg: 'var(--radius)',
+ md: 'calc(var(--radius) - 2px)',
+ sm: 'calc(var(--radius) - 4px)',
+ },
+ fontSize: {
+ // 1rem = 16px
+ /** 80px size / 84px high / bold */
+ mega: ['5rem', { lineHeight: '5.25rem', fontWeight: '700' }],
+ /** 56px size / 62px high / bold */
+ h1: ['3.5rem', { lineHeight: '3.875rem', fontWeight: '700' }],
+ /** 40px size / 48px high / bold */
+ h2: ['2.5rem', { lineHeight: '3rem', fontWeight: '700' }],
+ /** 32px size / 36px high / bold */
+ h3: ['2rem', { lineHeight: '2.25rem', fontWeight: '700' }],
+ /** 28px size / 36px high / bold */
+ h4: ['1.75rem', { lineHeight: '2.25rem', fontWeight: '700' }],
+ /** 24px size / 32px high / bold */
+ h5: ['1.5rem', { lineHeight: '2rem', fontWeight: '700' }],
+ /** 16px size / 20px high / bold */
+ h6: ['1rem', { lineHeight: '1.25rem', fontWeight: '700' }],
+
+ /** 32px size / 36px high / normal */
+ 'body-2xl': ['2rem', { lineHeight: '2.25rem' }],
+ /** 28px size / 36px high / normal */
+ 'body-xl': ['1.75rem', { lineHeight: '2.25rem' }],
+ /** 24px size / 32px high / normal */
+ 'body-lg': ['1.5rem', { lineHeight: '2rem' }],
+ /** 20px size / 28px high / normal */
+ 'body-md': ['1.25rem', { lineHeight: '1.75rem' }],
+ /** 16px size / 20px high / normal */
+ 'body-sm': ['1rem', { lineHeight: '1.25rem' }],
+ /** 14px size / 18px high / normal */
+ 'body-xs': ['0.875rem', { lineHeight: '1.125rem' }],
+ /** 12px size / 16px high / normal */
+ 'body-2xs': ['0.75rem', { lineHeight: '1rem' }],
+
+ /** 18px size / 24px high / semibold */
+ caption: ['1.125rem', { lineHeight: '1.5rem', fontWeight: '600' }],
+ /** 12px size / 16px high / bold */
+ button: ['0.75rem', { lineHeight: '1rem', fontWeight: '700' }],
+ },
+ keyframes: {
+ 'caret-blink': {
+ '0%,70%,100%': { opacity: '1' },
+ '20%,50%': { opacity: '0' },
+ },
+ },
+ animation: {
+ 'caret-blink': 'caret-blink 1.25s ease-out infinite',
+ },
+} satisfies Config['theme']
diff --git a/app/utils/honeypot.server.ts b/app/utils/honeypot.server.ts
new file mode 100644
index 0000000..91e6bcb
--- /dev/null
+++ b/app/utils/honeypot.server.ts
@@ -0,0 +1,17 @@
+import { Honeypot, SpamError } from 'remix-utils/honeypot/server'
+
+export const honeypot = new Honeypot({
+ validFromFieldName: process.env.NODE_ENV === 'test' ? null : undefined,
+ encryptionSeed: process.env.HONEYPOT_SECRET,
+})
+
+export function checkHoneypot(formData: FormData) {
+ try {
+ honeypot.check(formData)
+ } catch (error) {
+ if (error instanceof SpamError) {
+ throw new Response('Form not submitted properly', { status: 400 })
+ }
+ throw error
+ }
+}
diff --git a/app/utils/litefs.server.ts b/app/utils/litefs.server.ts
new file mode 100644
index 0000000..0565a5b
--- /dev/null
+++ b/app/utils/litefs.server.ts
@@ -0,0 +1,10 @@
+// litefs-js should be used server-side only. It imports `fs` which results in Remix
+// including a big polyfill. So we put the import in a `.server.ts` file to avoid that
+// polyfill from being included. https://github.com/epicweb-dev/epic-stack/pull/331
+export {
+ getInstanceInfo,
+ getAllInstances,
+ getInternalInstanceDomain,
+ getInstanceInfoSync,
+} from 'litefs-js'
+export { ensurePrimary, ensureInstance } from 'litefs-js/remix.js'
diff --git a/app/utils/misc.error-message.test.ts b/app/utils/misc.error-message.test.ts
new file mode 100644
index 0000000..1fe4d7a
--- /dev/null
+++ b/app/utils/misc.error-message.test.ts
@@ -0,0 +1,24 @@
+import { faker } from '@faker-js/faker'
+import { expect, test } from 'vitest'
+import { consoleError } from '#tests/setup/setup-test-env.ts'
+import { getErrorMessage } from './misc.tsx'
+
+test('Error object returns message', () => {
+ const message = faker.lorem.words(2)
+ expect(getErrorMessage(new Error(message))).toBe(message)
+})
+
+test('String returns itself', () => {
+ const message = faker.lorem.words(2)
+ expect(getErrorMessage(message)).toBe(message)
+})
+
+test('undefined falls back to Unknown', () => {
+ consoleError.mockImplementation(() => {})
+ expect(getErrorMessage(undefined)).toBe('Unknown Error')
+ expect(consoleError).toHaveBeenCalledWith(
+ 'Unable to get error message for error',
+ undefined,
+ )
+ expect(consoleError).toHaveBeenCalledTimes(1)
+})
diff --git a/app/utils/misc.tsx b/app/utils/misc.tsx
new file mode 100644
index 0000000..cd8e7e1
--- /dev/null
+++ b/app/utils/misc.tsx
@@ -0,0 +1,290 @@
+import { useFormAction, useNavigation } from '@remix-run/react'
+import { clsx, type ClassValue } from 'clsx'
+import { useEffect, useMemo, useRef, useState } from 'react'
+import { useSpinDelay } from 'spin-delay'
+import { extendTailwindMerge } from 'tailwind-merge'
+import { extendedTheme } from './extended-theme.ts'
+
+export function getUserImgSrc(imageId?: string | null) {
+ return imageId ? `/resources/user-images/${imageId}` : '/img/user.png'
+}
+
+export function getNoteImgSrc(imageId: string) {
+ return `/resources/note-images/${imageId}`
+}
+
+export function getErrorMessage(error: unknown) {
+ if (typeof error === 'string') return error
+ if (
+ error &&
+ typeof error === 'object' &&
+ 'message' in error &&
+ typeof error.message === 'string'
+ ) {
+ return error.message
+ }
+ console.error('Unable to get error message for error', error)
+ return 'Unknown Error'
+}
+
+function formatColors() {
+ const colors = []
+ for (const [key, color] of Object.entries(extendedTheme.colors)) {
+ if (typeof color === 'string') {
+ colors.push(key)
+ } else {
+ const colorGroup = Object.keys(color).map((subKey) =>
+ subKey === 'DEFAULT' ? '' : subKey,
+ )
+ colors.push({ [key]: colorGroup })
+ }
+ }
+ return colors
+}
+
+const customTwMerge = extendTailwindMerge({
+ extend: {
+ theme: {
+ colors: formatColors(),
+ borderRadius: Object.keys(extendedTheme.borderRadius),
+ },
+ classGroups: {
+ 'font-size': [
+ {
+ text: Object.keys(extendedTheme.fontSize),
+ },
+ ],
+ },
+ },
+})
+
+export function cn(...inputs: ClassValue[]) {
+ return customTwMerge(clsx(inputs))
+}
+
+export function getDomainUrl(request: Request) {
+ const host =
+ request.headers.get('X-Forwarded-Host') ??
+ request.headers.get('host') ??
+ new URL(request.url).host
+ const protocol = request.headers.get('X-Forwarded-Proto') ?? 'http'
+ return `${protocol}://${host}`
+}
+
+export function getReferrerRoute(request: Request) {
+ // spelling errors and whatever makes this annoyingly inconsistent
+ // in my own testing, `referer` returned the right value, but đ¤ˇââď¸
+ const referrer =
+ request.headers.get('referer') ??
+ request.headers.get('referrer') ??
+ request.referrer
+ const domain = getDomainUrl(request)
+ if (referrer?.startsWith(domain)) {
+ return referrer.slice(domain.length)
+ } else {
+ return '/'
+ }
+}
+
+/**
+ * Merge multiple headers objects into one (uses set so headers are overridden)
+ */
+export function mergeHeaders(
+ ...headers: Array
+) {
+ const merged = new Headers()
+ for (const header of headers) {
+ if (!header) continue
+ for (const [key, value] of new Headers(header).entries()) {
+ merged.set(key, value)
+ }
+ }
+ return merged
+}
+
+/**
+ * Combine multiple header objects into one (uses append so headers are not overridden)
+ */
+export function combineHeaders(
+ ...headers: Array
+) {
+ const combined = new Headers()
+ for (const header of headers) {
+ if (!header) continue
+ for (const [key, value] of new Headers(header).entries()) {
+ combined.append(key, value)
+ }
+ }
+ return combined
+}
+
+/**
+ * Combine multiple response init objects into one (uses combineHeaders)
+ */
+export function combineResponseInits(
+ ...responseInits: Array
+) {
+ let combined: ResponseInit = {}
+ for (const responseInit of responseInits) {
+ combined = {
+ ...responseInit,
+ headers: combineHeaders(combined.headers, responseInit?.headers),
+ }
+ }
+ return combined
+}
+
+/**
+ * Returns true if the current navigation is submitting the current route's
+ * form. Defaults to the current route's form action and method POST.
+ *
+ * Defaults state to 'non-idle'
+ *
+ * NOTE: the default formAction will include query params, but the
+ * navigation.formAction will not, so don't use the default formAction if you
+ * want to know if a form is submitting without specific query params.
+ */
+export function useIsPending({
+ formAction,
+ formMethod = 'POST',
+ state = 'non-idle',
+}: {
+ formAction?: string
+ formMethod?: 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE'
+ state?: 'submitting' | 'loading' | 'non-idle'
+} = {}) {
+ const contextualFormAction = useFormAction()
+ const navigation = useNavigation()
+ const isPendingState =
+ state === 'non-idle'
+ ? navigation.state !== 'idle'
+ : navigation.state === state
+ return (
+ isPendingState &&
+ navigation.formAction === (formAction ?? contextualFormAction) &&
+ navigation.formMethod === formMethod
+ )
+}
+
+/**
+ * This combines useSpinDelay (from https://npm.im/spin-delay) and useIsPending
+ * from our own utilities to give you a nice way to show a loading spinner for
+ * a minimum amount of time, even if the request finishes right after the delay.
+ *
+ * This avoids a flash of loading state regardless of how fast or slow the
+ * request is.
+ */
+export function useDelayedIsPending({
+ formAction,
+ formMethod,
+ delay = 400,
+ minDuration = 300,
+}: Parameters[0] &
+ Parameters[1] = {}) {
+ const isPending = useIsPending({ formAction, formMethod })
+ const delayedIsPending = useSpinDelay(isPending, {
+ delay,
+ minDuration,
+ })
+ return delayedIsPending
+}
+
+function callAll>(
+ ...fns: Array<((...args: Args) => unknown) | undefined>
+) {
+ return (...args: Args) => fns.forEach((fn) => fn?.(...args))
+}
+
+/**
+ * Use this hook with a button and it will make it so the first click sets a
+ * `doubleCheck` state to true, and the second click will actually trigger the
+ * `onClick` handler. This allows you to have a button that can be like a
+ * "are you sure?" experience for the user before doing destructive operations.
+ */
+export function useDoubleCheck() {
+ const [doubleCheck, setDoubleCheck] = useState(false)
+
+ function getButtonProps(
+ props?: React.ButtonHTMLAttributes,
+ ) {
+ const onBlur: React.ButtonHTMLAttributes['onBlur'] =
+ () => setDoubleCheck(false)
+
+ const onClick: React.ButtonHTMLAttributes['onClick'] =
+ doubleCheck
+ ? undefined
+ : (e) => {
+ e.preventDefault()
+ setDoubleCheck(true)
+ }
+
+ const onKeyUp: React.ButtonHTMLAttributes['onKeyUp'] = (
+ e,
+ ) => {
+ if (e.key === 'Escape') {
+ setDoubleCheck(false)
+ }
+ }
+
+ return {
+ ...props,
+ onBlur: callAll(onBlur, props?.onBlur),
+ onClick: callAll(onClick, props?.onClick),
+ onKeyUp: callAll(onKeyUp, props?.onKeyUp),
+ }
+ }
+
+ return { doubleCheck, getButtonProps }
+}
+
+/**
+ * Simple debounce implementation
+ */
+function debounce) => void>(
+ fn: Callback,
+ delay: number,
+) {
+ let timer: ReturnType | null = null
+ return (...args: Parameters) => {
+ if (timer) clearTimeout(timer)
+ timer = setTimeout(() => {
+ fn(...args)
+ }, delay)
+ }
+}
+
+/**
+ * Debounce a callback function
+ */
+export function useDebounce<
+ Callback extends (...args: Parameters) => ReturnType,
+>(callback: Callback, delay: number) {
+ const callbackRef = useRef(callback)
+ useEffect(() => {
+ callbackRef.current = callback
+ })
+ return useMemo(
+ () =>
+ debounce(
+ (...args: Parameters) => callbackRef.current(...args),
+ delay,
+ ),
+ [delay],
+ )
+}
+
+export async function downloadFile(url: string, retries: number = 0) {
+ const MAX_RETRIES = 3
+ try {
+ const response = await fetch(url)
+ if (!response.ok) {
+ throw new Error(`Failed to fetch image with status ${response.status}`)
+ }
+ const contentType = response.headers.get('content-type') ?? 'image/jpg'
+ const blob = Buffer.from(await response.arrayBuffer())
+ return { contentType, blob }
+ } catch (e) {
+ if (retries > MAX_RETRIES) throw e
+ return downloadFile(url, retries + 1)
+ }
+}
diff --git a/app/utils/misc.use-double-check.test.tsx b/app/utils/misc.use-double-check.test.tsx
new file mode 100644
index 0000000..4adfa59
--- /dev/null
+++ b/app/utils/misc.use-double-check.test.tsx
@@ -0,0 +1,83 @@
+/**
+ * @vitest-environment jsdom
+ */
+import { render, screen } from '@testing-library/react'
+import { userEvent } from '@testing-library/user-event'
+import { useState } from 'react'
+import { expect, test } from 'vitest'
+import { useDoubleCheck } from './misc.tsx'
+
+function TestComponent() {
+ const [defaultPrevented, setDefaultPrevented] = useState<
+ 'idle' | 'no' | 'yes'
+ >('idle')
+ const dc = useDoubleCheck()
+ return (
+
+ Default Prevented: {defaultPrevented}
+
+ setDefaultPrevented(e.defaultPrevented ? 'yes' : 'no'),
+ })}
+ >
+ {dc.doubleCheck ? 'You sure?' : 'Click me'}
+
+
+ )
+}
+
+test('prevents default on the first click, and does not on the second', async () => {
+ const user = userEvent.setup()
+ render( )
+
+ const status = screen.getByRole('status')
+ const button = screen.getByRole('button')
+
+ expect(status).toHaveTextContent('Default Prevented: idle')
+ expect(button).toHaveTextContent('Click me')
+
+ await user.click(button)
+ expect(button).toHaveTextContent('You sure?')
+ expect(status).toHaveTextContent('Default Prevented: yes')
+
+ await user.click(button)
+ expect(button).toHaveTextContent('You sure?')
+ expect(status).toHaveTextContent('Default Prevented: no')
+})
+
+test('blurring the button starts things over', async () => {
+ const user = userEvent.setup()
+ render( )
+
+ const status = screen.getByRole('status')
+ const button = screen.getByRole('button')
+
+ await user.click(button)
+ expect(button).toHaveTextContent('You sure?')
+ expect(status).toHaveTextContent('Default Prevented: yes')
+
+ await user.click(document.body)
+ // button goes back to click me
+ expect(button).toHaveTextContent('Click me')
+ // our callback wasn't called, so the status doesn't change
+ expect(status).toHaveTextContent('Default Prevented: yes')
+})
+
+test('hitting "escape" on the input starts things over', async () => {
+ const user = userEvent.setup()
+ render( )
+
+ const status = screen.getByRole('status')
+ const button = screen.getByRole('button')
+
+ await user.click(button)
+ expect(button).toHaveTextContent('You sure?')
+ expect(status).toHaveTextContent('Default Prevented: yes')
+
+ await user.keyboard('{Escape}')
+ // button goes back to click me
+ expect(button).toHaveTextContent('Click me')
+ // our callback wasn't called, so the status doesn't change
+ expect(status).toHaveTextContent('Default Prevented: yes')
+})
diff --git a/app/utils/monitoring.client.tsx b/app/utils/monitoring.client.tsx
new file mode 100644
index 0000000..afe91b2
--- /dev/null
+++ b/app/utils/monitoring.client.tsx
@@ -0,0 +1,47 @@
+import { useLocation, useMatches } from '@remix-run/react'
+import {
+ init as sentryInit,
+ browserTracingIntegration,
+ replayIntegration,
+ browserProfilingIntegration,
+} from '@sentry/remix'
+import { useEffect } from 'react'
+
+export function init() {
+ sentryInit({
+ dsn: ENV.SENTRY_DSN,
+ environment: ENV.MODE,
+ beforeSend(event) {
+ if (event.request?.url) {
+ const url = new URL(event.request.url)
+ if (
+ url.protocol === 'chrome-extension:' ||
+ url.protocol === 'moz-extension:'
+ ) {
+ // This error is from a browser extension, ignore it
+ return null
+ }
+ }
+ return event
+ },
+ integrations: [
+ browserTracingIntegration({
+ useEffect,
+ useLocation,
+ useMatches,
+ }),
+ replayIntegration(),
+ browserProfilingIntegration(),
+ ],
+
+ // Set tracesSampleRate to 1.0 to capture 100%
+ // of transactions for performance monitoring.
+ // We recommend adjusting this value in production
+ tracesSampleRate: 1.0,
+
+ // Capture Replay for 10% of all sessions,
+ // plus for 100% of sessions with an error
+ replaysSessionSampleRate: 0.1,
+ replaysOnErrorSampleRate: 1.0,
+ })
+}
diff --git a/app/utils/nonce-provider.ts b/app/utils/nonce-provider.ts
new file mode 100644
index 0000000..41bb980
--- /dev/null
+++ b/app/utils/nonce-provider.ts
@@ -0,0 +1,5 @@
+import * as React from 'react'
+
+export const NonceContext = React.createContext('')
+export const NonceProvider = NonceContext.Provider
+export const useNonce = () => React.useContext(NonceContext)
diff --git a/app/utils/permissions.server.ts b/app/utils/permissions.server.ts
new file mode 100644
index 0000000..d96fa91
--- /dev/null
+++ b/app/utils/permissions.server.ts
@@ -0,0 +1,60 @@
+import { json } from '@remix-run/node'
+import { requireUserId } from './auth.server.ts'
+import { prisma } from './db.server.ts'
+import { type PermissionString, parsePermissionString } from './user.ts'
+
+export async function requireUserWithPermission(
+ request: Request,
+ permission: PermissionString,
+) {
+ const userId = await requireUserId(request)
+ const permissionData = parsePermissionString(permission)
+ const user = await prisma.user.findFirst({
+ select: { id: true },
+ where: {
+ id: userId,
+ roles: {
+ some: {
+ permissions: {
+ some: {
+ ...permissionData,
+ access: permissionData.access
+ ? { in: permissionData.access }
+ : undefined,
+ },
+ },
+ },
+ },
+ },
+ })
+ if (!user) {
+ throw json(
+ {
+ error: 'Unauthorized',
+ requiredPermission: permissionData,
+ message: `Unauthorized: required permissions: ${permission}`,
+ },
+ { status: 403 },
+ )
+ }
+ return user.id
+}
+
+export async function requireUserWithRole(request: Request, name: string) {
+ const userId = await requireUserId(request)
+ const user = await prisma.user.findFirst({
+ select: { id: true },
+ where: { id: userId, roles: { some: { name } } },
+ })
+ if (!user) {
+ throw json(
+ {
+ error: 'Unauthorized',
+ requiredRole: name,
+ message: `Unauthorized: required role: ${name}`,
+ },
+ { status: 403 },
+ )
+ }
+ return user.id
+}
diff --git a/app/utils/providers/constants.ts b/app/utils/providers/constants.ts
new file mode 100644
index 0000000..b8737a0
--- /dev/null
+++ b/app/utils/providers/constants.ts
@@ -0,0 +1,3 @@
+export const MOCK_CODE_GITHUB = 'MOCK_CODE_GITHUB_KODY'
+
+export const MOCK_CODE_GITHUB_HEADER = 'x-mock-code-github'
diff --git a/app/utils/providers/github.server.ts b/app/utils/providers/github.server.ts
new file mode 100644
index 0000000..895271b
--- /dev/null
+++ b/app/utils/providers/github.server.ts
@@ -0,0 +1,106 @@
+import { createId as cuid } from '@paralleldrive/cuid2'
+import { redirect } from '@remix-run/node'
+import { GitHubStrategy } from 'remix-auth-github'
+import { z } from 'zod'
+import { cache, cachified } from '../cache.server.ts'
+import { connectionSessionStorage } from '../connections.server.ts'
+import { type Timings } from '../timing.server.ts'
+import { MOCK_CODE_GITHUB_HEADER, MOCK_CODE_GITHUB } from './constants.ts'
+import { type AuthProvider } from './provider.ts'
+
+const GitHubUserSchema = z.object({ login: z.string() })
+const GitHubUserParseResult = z
+ .object({
+ success: z.literal(true),
+ data: GitHubUserSchema,
+ })
+ .or(
+ z.object({
+ success: z.literal(false),
+ }),
+ )
+
+const shouldMock =
+ process.env.GITHUB_CLIENT_ID?.startsWith('MOCK_') ||
+ process.env.NODE_ENV === 'test'
+
+export class GitHubProvider implements AuthProvider {
+ getAuthStrategy() {
+ return new GitHubStrategy(
+ {
+ clientID: process.env.GITHUB_CLIENT_ID,
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
+ callbackURL: '/auth/github/callback',
+ },
+ async ({ profile }) => {
+ const email = profile.emails[0]?.value.trim().toLowerCase()
+ if (!email) {
+ throw new Error('Email not found')
+ }
+ const username = profile.displayName
+ const imageUrl = profile.photos[0].value
+ return {
+ email,
+ id: profile.id,
+ username,
+ name: profile.name.givenName,
+ imageUrl,
+ }
+ },
+ )
+ }
+
+ async resolveConnectionData(
+ providerId: string,
+ { timings }: { timings?: Timings } = {},
+ ) {
+ const result = await cachified({
+ key: `connection-data:github:${providerId}`,
+ cache,
+ timings,
+ ttl: 1000 * 60,
+ swr: 1000 * 60 * 60 * 24 * 7,
+ async getFreshValue(context) {
+ const response = await fetch(
+ `https://api.github.com/user/${providerId}`,
+ { headers: { Authorization: `token ${process.env.GITHUB_TOKEN}` } },
+ )
+ const rawJson = await response.json()
+ const result = GitHubUserSchema.safeParse(rawJson)
+ if (!result.success) {
+ // if it was unsuccessful, then we should kick it out of the cache
+ // asap and try again.
+ context.metadata.ttl = 0
+ }
+ return result
+ },
+ checkValue: GitHubUserParseResult,
+ })
+ return {
+ displayName: result.success ? result.data.login : 'Unknown',
+ link: result.success ? `https://github.com/${result.data.login}` : null,
+ } as const
+ }
+
+ async handleMockAction(request: Request) {
+ if (!shouldMock) return
+
+ const connectionSession = await connectionSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const state = cuid()
+ connectionSession.set('oauth2:state', state)
+
+ // allows us to inject a code when running e2e tests,
+ // but falls back to a pre-defined đ¨ constant
+ const code =
+ request.headers.get(MOCK_CODE_GITHUB_HEADER) || MOCK_CODE_GITHUB
+ const searchParams = new URLSearchParams({ code, state })
+ throw redirect(`/auth/github/callback?${searchParams}`, {
+ headers: {
+ 'set-cookie':
+ await connectionSessionStorage.commitSession(connectionSession),
+ },
+ })
+ }
+}
diff --git a/app/utils/providers/provider.ts b/app/utils/providers/provider.ts
new file mode 100644
index 0000000..834de1f
--- /dev/null
+++ b/app/utils/providers/provider.ts
@@ -0,0 +1,28 @@
+import { type Strategy } from 'remix-auth'
+import { type Timings } from '../timing.server.ts'
+
+// Define a user type for cleaner typing
+export type ProviderUser = {
+ id: string
+ email: string
+ username?: string
+ name?: string
+ imageUrl?: string
+}
+
+export interface AuthProvider {
+ getAuthStrategy(): Strategy
+ handleMockAction(request: Request): Promise
+ resolveConnectionData(
+ providerId: string,
+ options?: { timings?: Timings },
+ ): Promise<{
+ displayName: string
+ link?: string | null
+ }>
+}
+
+export const normalizeEmail = (s: string) => s.toLowerCase()
+
+export const normalizeUsername = (s: string) =>
+ s.replace(/[^a-zA-Z0-9_]/g, '_').toLowerCase()
diff --git a/app/utils/redirect-cookie.server.ts b/app/utils/redirect-cookie.server.ts
new file mode 100644
index 0000000..0008537
--- /dev/null
+++ b/app/utils/redirect-cookie.server.ts
@@ -0,0 +1,17 @@
+import * as cookie from 'cookie'
+
+const key = 'redirectTo'
+export const destroyRedirectToHeader = cookie.serialize(key, '', { maxAge: -1 })
+
+export function getRedirectCookieHeader(redirectTo?: string) {
+ return redirectTo && redirectTo !== '/'
+ ? cookie.serialize(key, redirectTo, { maxAge: 60 * 10 })
+ : null
+}
+
+export function getRedirectCookieValue(request: Request) {
+ const rawCookie = request.headers.get('cookie')
+ const parsedCookies = rawCookie ? cookie.parse(rawCookie) : {}
+ const redirectTo = parsedCookies[key]
+ return redirectTo || null
+}
diff --git a/app/utils/request-info.ts b/app/utils/request-info.ts
new file mode 100644
index 0000000..1dd48dd
--- /dev/null
+++ b/app/utils/request-info.ts
@@ -0,0 +1,13 @@
+import { invariant } from '@epic-web/invariant'
+import { useRouteLoaderData } from '@remix-run/react'
+import { type loader as rootLoader } from '#app/root.tsx'
+
+/**
+ * @returns the request info from the root loader
+ */
+export function useRequestInfo() {
+ const data = useRouteLoaderData('root')
+ invariant(data?.requestInfo, 'No requestInfo found in root loader')
+
+ return data.requestInfo
+}
diff --git a/app/utils/session.server.ts b/app/utils/session.server.ts
new file mode 100644
index 0000000..f155000
--- /dev/null
+++ b/app/utils/session.server.ts
@@ -0,0 +1,38 @@
+import { createCookieSessionStorage } from '@remix-run/node'
+
+export const authSessionStorage = createCookieSessionStorage({
+ cookie: {
+ name: 'en_session',
+ sameSite: 'lax', // CSRF protection is advised if changing to 'none'
+ path: '/',
+ httpOnly: true,
+ secrets: process.env.SESSION_SECRET.split(','),
+ secure: process.env.NODE_ENV === 'production',
+ },
+})
+
+// we have to do this because every time you commit the session you overwrite it
+// so we store the expiration time in the cookie and reset it every time we commit
+const originalCommitSession = authSessionStorage.commitSession
+
+Object.defineProperty(authSessionStorage, 'commitSession', {
+ value: async function commitSession(
+ ...args: Parameters
+ ) {
+ const [session, options] = args
+ if (options?.expires) {
+ session.set('expires', options.expires)
+ }
+ if (options?.maxAge) {
+ session.set('expires', new Date(Date.now() + options.maxAge * 1000))
+ }
+ const expires = session.has('expires')
+ ? new Date(session.get('expires'))
+ : undefined
+ const setCookieHeader = await originalCommitSession(session, {
+ ...options,
+ expires,
+ })
+ return setCookieHeader
+ },
+})
diff --git a/app/utils/theme.server.ts b/app/utils/theme.server.ts
new file mode 100644
index 0000000..1d60cbc
--- /dev/null
+++ b/app/utils/theme.server.ts
@@ -0,0 +1,19 @@
+import * as cookie from 'cookie'
+
+const cookieName = 'en_theme'
+export type Theme = 'light' | 'dark'
+
+export function getTheme(request: Request): Theme | null {
+ const cookieHeader = request.headers.get('cookie')
+ const parsed = cookieHeader ? cookie.parse(cookieHeader)[cookieName] : 'light'
+ if (parsed === 'light' || parsed === 'dark') return parsed
+ return null
+}
+
+export function setTheme(theme: Theme | 'system') {
+ if (theme === 'system') {
+ return cookie.serialize(cookieName, '', { path: '/', maxAge: -1 })
+ } else {
+ return cookie.serialize(cookieName, theme, { path: '/', maxAge: 31536000 })
+ }
+}
diff --git a/app/utils/timing.server.ts b/app/utils/timing.server.ts
new file mode 100644
index 0000000..3904647
--- /dev/null
+++ b/app/utils/timing.server.ts
@@ -0,0 +1,121 @@
+import { type CreateReporter } from '@epic-web/cachified'
+
+export type Timings = Record<
+ string,
+ Array<
+ { desc?: string } & (
+ | { time: number; start?: never }
+ | { time?: never; start: number }
+ )
+ >
+>
+
+export function makeTimings(type: string, desc?: string) {
+ const timings: Timings = {
+ [type]: [{ desc, start: performance.now() }],
+ }
+ Object.defineProperty(timings, 'toString', {
+ value: function () {
+ return getServerTimeHeader(timings)
+ },
+ enumerable: false,
+ })
+ return timings
+}
+
+function createTimer(type: string, desc?: string) {
+ const start = performance.now()
+ return {
+ end(timings: Timings) {
+ let timingType = timings[type]
+
+ if (!timingType) {
+ timingType = timings[type] = []
+ }
+ timingType.push({ desc, time: performance.now() - start })
+ },
+ }
+}
+
+export async function time(
+ fn: Promise | (() => ReturnType | Promise),
+ {
+ type,
+ desc,
+ timings,
+ }: {
+ type: string
+ desc?: string
+ timings?: Timings
+ },
+): Promise {
+ const timer = createTimer(type, desc)
+ const promise = typeof fn === 'function' ? fn() : fn
+ if (!timings) return promise
+
+ const result = await promise
+
+ timer.end(timings)
+ return result
+}
+
+export function getServerTimeHeader(timings?: Timings) {
+ if (!timings) return ''
+ return Object.entries(timings)
+ .map(([key, timingInfos]) => {
+ const dur = timingInfos
+ .reduce((acc, timingInfo) => {
+ const time = timingInfo.time ?? performance.now() - timingInfo.start
+ return acc + time
+ }, 0)
+ .toFixed(1)
+ const desc = timingInfos
+ .map((t) => t.desc)
+ .filter(Boolean)
+ .join(' & ')
+ return [
+ key.replaceAll(/(:| |@|=|;|,|\/|\\)/g, '_'),
+ desc ? `desc=${JSON.stringify(desc)}` : null,
+ `dur=${dur}`,
+ ]
+ .filter(Boolean)
+ .join(';')
+ })
+ .join(',')
+}
+
+export function combineServerTimings(headers1: Headers, headers2: Headers) {
+ const newHeaders = new Headers(headers1)
+ newHeaders.append('Server-Timing', headers2.get('Server-Timing') ?? '')
+ return newHeaders.get('Server-Timing') ?? ''
+}
+
+export function cachifiedTimingReporter(
+ timings?: Timings,
+): undefined | CreateReporter {
+ if (!timings) return
+
+ return ({ key }) => {
+ const cacheRetrievalTimer = createTimer(
+ `cache:${key}`,
+ `${key} cache retrieval`,
+ )
+ let getFreshValueTimer: ReturnType | undefined
+ return (event) => {
+ switch (event.name) {
+ case 'getFreshValueStart':
+ getFreshValueTimer = createTimer(
+ `getFreshValue:${key}`,
+ `request forced to wait for a fresh ${key} value`,
+ )
+ break
+ case 'getFreshValueSuccess':
+ getFreshValueTimer?.end(timings)
+ break
+ case 'done':
+ cacheRetrievalTimer.end(timings)
+ break
+ }
+ }
+ }
+}
diff --git a/app/utils/toast.server.ts b/app/utils/toast.server.ts
new file mode 100644
index 0000000..d25b064
--- /dev/null
+++ b/app/utils/toast.server.ts
@@ -0,0 +1,62 @@
+import { createId as cuid } from '@paralleldrive/cuid2'
+import { createCookieSessionStorage, redirect } from '@remix-run/node'
+import { z } from 'zod'
+import { combineHeaders } from './misc.tsx'
+
+export const toastKey = 'toast'
+
+const ToastSchema = z.object({
+ description: z.string(),
+ id: z.string().default(() => cuid()),
+ title: z.string().optional(),
+ type: z.enum(['message', 'success', 'error']).default('message'),
+})
+
+export type Toast = z.infer
+export type ToastInput = z.input
+
+export const toastSessionStorage = createCookieSessionStorage({
+ cookie: {
+ name: 'en_toast',
+ sameSite: 'lax',
+ path: '/',
+ httpOnly: true,
+ secrets: process.env.SESSION_SECRET.split(','),
+ secure: process.env.NODE_ENV === 'production',
+ },
+})
+
+export async function redirectWithToast(
+ url: string,
+ toast: ToastInput,
+ init?: ResponseInit,
+) {
+ return redirect(url, {
+ ...init,
+ headers: combineHeaders(init?.headers, await createToastHeaders(toast)),
+ })
+}
+
+export async function createToastHeaders(toastInput: ToastInput) {
+ const session = await toastSessionStorage.getSession()
+ const toast = ToastSchema.parse(toastInput)
+ session.flash(toastKey, toast)
+ const cookie = await toastSessionStorage.commitSession(session)
+ return new Headers({ 'set-cookie': cookie })
+}
+
+export async function getToast(request: Request) {
+ const session = await toastSessionStorage.getSession(
+ request.headers.get('cookie'),
+ )
+ const result = ToastSchema.safeParse(session.get(toastKey))
+ const toast = result.success ? result.data : null
+ return {
+ toast,
+ headers: toast
+ ? new Headers({
+ 'set-cookie': await toastSessionStorage.destroySession(session),
+ })
+ : null,
+ }
+}
diff --git a/app/utils/totp.server.ts b/app/utils/totp.server.ts
new file mode 100644
index 0000000..bc5ff26
--- /dev/null
+++ b/app/utils/totp.server.ts
@@ -0,0 +1,3 @@
+// @epic-web/totp should be used server-side only. It imports `Crypto` which results in Remix
+// including a big polyfill. So we put the import in a `.server.ts` file to avoid that
+export * from '@epic-web/totp'
diff --git a/app/utils/user-validation.ts b/app/utils/user-validation.ts
new file mode 100644
index 0000000..9515823
--- /dev/null
+++ b/app/utils/user-validation.ts
@@ -0,0 +1,42 @@
+import { z } from 'zod'
+
+export const USERNAME_MIN_LENGTH = 3
+export const USERNAME_MAX_LENGTH = 20
+
+export const UsernameSchema = z
+ .string({ required_error: 'Username is required' })
+ .min(USERNAME_MIN_LENGTH, { message: 'Username is too short' })
+ .max(USERNAME_MAX_LENGTH, { message: 'Username is too long' })
+ .regex(/^[a-zA-Z0-9_]+$/, {
+ message: 'Username can only include letters, numbers, and underscores',
+ })
+ // users can type the username in any case, but we store it in lowercase
+ .transform((value) => value.toLowerCase())
+
+export const PasswordSchema = z
+ .string({ required_error: 'Password is required' })
+ .min(6, { message: 'Password is too short' })
+ .max(100, { message: 'Password is too long' })
+export const NameSchema = z
+ .string({ required_error: 'Name is required' })
+ .min(3, { message: 'Name is too short' })
+ .max(40, { message: 'Name is too long' })
+export const EmailSchema = z
+ .string({ required_error: 'Email is required' })
+ .email({ message: 'Email is invalid' })
+ .min(3, { message: 'Email is too short' })
+ .max(100, { message: 'Email is too long' })
+ // users can type the email in any case, but we store it in lowercase
+ .transform((value) => value.toLowerCase())
+
+export const PasswordAndConfirmPasswordSchema = z
+ .object({ password: PasswordSchema, confirmPassword: PasswordSchema })
+ .superRefine(({ confirmPassword, password }, ctx) => {
+ if (confirmPassword !== password) {
+ ctx.addIssue({
+ path: ['confirmPassword'],
+ code: 'custom',
+ message: 'The passwords must match',
+ })
+ }
+ })
diff --git a/app/utils/user.ts b/app/utils/user.ts
new file mode 100644
index 0000000..735915b
--- /dev/null
+++ b/app/utils/user.ts
@@ -0,0 +1,69 @@
+import { type SerializeFrom } from '@remix-run/node'
+import { useRouteLoaderData } from '@remix-run/react'
+import { type loader as rootLoader } from '#app/root.tsx'
+
+function isUser(user: any): user is SerializeFrom['user'] {
+ return user && typeof user === 'object' && typeof user.id === 'string'
+}
+
+export function useOptionalUser() {
+ const data = useRouteLoaderData('root')
+ if (!data || !isUser(data.user)) {
+ return undefined
+ }
+ return data.user
+}
+
+export function useUser() {
+ const maybeUser = useOptionalUser()
+ if (!maybeUser) {
+ throw new Error(
+ 'No user found in root loader, but user is required by useUser. If user is optional, try useOptionalUser instead.',
+ )
+ }
+ return maybeUser
+}
+
+type Action = 'create' | 'read' | 'update' | 'delete'
+type Entity = 'user' | 'note'
+type Access = 'own' | 'any' | 'own,any' | 'any,own'
+export type PermissionString =
+ | `${Action}:${Entity}`
+ | `${Action}:${Entity}:${Access}`
+
+export function parsePermissionString(permissionString: PermissionString) {
+ const [action, entity, access] = permissionString.split(':') as [
+ Action,
+ Entity,
+ Access | undefined,
+ ]
+ return {
+ action,
+ entity,
+ access: access ? (access.split(',') as Array) : undefined,
+ }
+}
+
+export function userHasPermission(
+ user: Pick, 'roles'> | null | undefined,
+ permission: PermissionString,
+) {
+ if (!user) return false
+ const { action, entity, access } = parsePermissionString(permission)
+ return user.roles.some((role) =>
+ role.permissions.some(
+ (permission) =>
+ permission.entity === entity &&
+ permission.action === action &&
+ (!access || access.includes(permission.access)),
+ ),
+ )
+}
+
+export function userHasRole(
+ user: Pick, 'roles'> | null,
+ role: string,
+) {
+ if (!user) return false
+ return user.roles.some((r) => r.name === role)
+}
diff --git a/app/utils/verification.server.ts b/app/utils/verification.server.ts
new file mode 100644
index 0000000..6cfc4a8
--- /dev/null
+++ b/app/utils/verification.server.ts
@@ -0,0 +1,13 @@
+import { createCookieSessionStorage } from '@remix-run/node'
+
+export const verifySessionStorage = createCookieSessionStorage({
+ cookie: {
+ name: 'en_verification',
+ sameSite: 'lax', // CSRF protection is advised if changing to 'none'
+ path: '/',
+ httpOnly: true,
+ maxAge: 60 * 10, // 10 minutes
+ secrets: process.env.SESSION_SECRET.split(','),
+ secure: process.env.NODE_ENV === 'production',
+ },
+})
diff --git a/components.json b/components.json
new file mode 100644
index 0000000..4897a3b
--- /dev/null
+++ b/components.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "app/styles/tailwind.css",
+ "baseColor": "slate",
+ "cssVariables": true
+ },
+ "aliases": {
+ "components": "#app/components",
+ "utils": "#app/utils/misc.tsx"
+ }
+}
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..611208a
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,7 @@
+import { default as defaultConfig } from '@epic-web/config/eslint'
+
+/** @type {import("eslint").Linter.Config} */
+export default [
+ ...defaultConfig,
+ // add custom config objects here:
+]
diff --git a/fly.toml b/fly.toml
new file mode 100644
index 0000000..fcb9708
--- /dev/null
+++ b/fly.toml
@@ -0,0 +1,61 @@
+app = "publicareproto"
+primary_region = "cdg"
+kill_signal = "SIGINT"
+kill_timeout = 5
+processes = [ ]
+swap_size_mb = 512
+
+[experimental]
+allowed_public_ports = [ ]
+auto_rollback = true
+
+[mounts]
+source = "data"
+destination = "/data"
+
+[build]
+dockerfile = "/other/Dockerfile"
+ignorefile = "/other/Dockerfile.dockerignore"
+
+[[services]]
+internal_port = 8080
+processes = [ "app" ]
+protocol = "tcp"
+script_checks = [ ]
+
+ [services.concurrency]
+ hard_limit = 100
+ soft_limit = 80
+ type = "requests"
+
+ [[services.ports]]
+ handlers = [ "http" ]
+ port = 80
+ force_https = true
+
+ [[services.ports]]
+ handlers = [ "tls", "http" ]
+ port = 443
+
+ [[services.tcp_checks]]
+ grace_period = "1s"
+ interval = "15s"
+ restart_limit = 0
+ timeout = "2s"
+
+ [[services.http_checks]]
+ interval = "10s"
+ grace_period = "5s"
+ method = "get"
+ path = "/resources/healthcheck"
+ protocol = "http"
+ timeout = "2s"
+ tls_skip_verify = false
+ headers = { }
+
+ [[services.http_checks]]
+ grace_period = "10s"
+ interval = "30s"
+ method = "GET"
+ timeout = "5s"
+ path = "/litefs/health"
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..bc7c79f
--- /dev/null
+++ b/index.js
@@ -0,0 +1,37 @@
+import 'dotenv/config'
+import * as fs from 'node:fs'
+import chalk from 'chalk'
+import closeWithGrace from 'close-with-grace'
+import sourceMapSupport from 'source-map-support'
+
+sourceMapSupport.install({
+ retrieveSourceMap: function (source) {
+ // get source file without the `file://` prefix or `?t=...` suffix
+ const match = source.match(/^file:\/\/(.*)\?t=[.\d]+$/)
+ if (match) {
+ return {
+ url: source,
+ map: fs.readFileSync(`${match[1]}.map`, 'utf8'),
+ }
+ }
+ return null
+ },
+})
+
+closeWithGrace(async ({ err }) => {
+ if (err) {
+ console.error(chalk.red(err))
+ console.error(chalk.red(err.stack))
+ process.exit(1)
+ }
+})
+
+if (process.env.MOCKS === 'true') {
+ await import('./tests/mocks/index.ts')
+}
+
+if (process.env.NODE_ENV === 'production') {
+ await import('./server-build/index.js')
+} else {
+ await import('./server/index.ts')
+}
diff --git a/other/Dockerfile b/other/Dockerfile
new file mode 100644
index 0000000..1e54b07
--- /dev/null
+++ b/other/Dockerfile
@@ -0,0 +1,95 @@
+# This file is moved to the root directory before building the image
+
+# base node image
+FROM node:20-bookworm-slim as base
+
+# set for base and all layer that inherit from it
+ENV NODE_ENV production
+
+# Install openssl for Prisma
+RUN apt-get update && apt-get install -y fuse3 openssl sqlite3 ca-certificates
+
+# Install all node_modules, including dev dependencies
+FROM base as deps
+
+WORKDIR /myapp
+
+ADD package.json package-lock.json .npmrc ./
+RUN npm install --include=dev
+
+# Setup production node_modules
+FROM base as production-deps
+
+WORKDIR /myapp
+
+COPY --from=deps /myapp/node_modules /myapp/node_modules
+ADD package.json package-lock.json .npmrc ./
+RUN npm prune --omit=dev
+
+# Build the app
+FROM base as build
+
+ARG COMMIT_SHA
+ENV COMMIT_SHA=$COMMIT_SHA
+
+# Use the following environment variables to configure Sentry
+# ENV SENTRY_ORG=
+# ENV SENTRY_PROJECT=
+
+
+WORKDIR /myapp
+
+COPY --from=deps /myapp/node_modules /myapp/node_modules
+
+ADD prisma .
+RUN npx prisma generate
+
+ADD . .
+
+# Mount the secret and set it as an environment variable and run the build
+RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN \
+ export SENTRY_AUTH_TOKEN=$(cat /run/secrets/SENTRY_AUTH_TOKEN) && \
+ npm run build
+
+# Finally, build the production image with minimal footprint
+FROM base
+
+ENV FLY="true"
+ENV LITEFS_DIR="/litefs/data"
+ENV DATABASE_FILENAME="sqlite.db"
+ENV DATABASE_PATH="$LITEFS_DIR/$DATABASE_FILENAME"
+ENV DATABASE_URL="file:$DATABASE_PATH"
+ENV CACHE_DATABASE_FILENAME="cache.db"
+ENV CACHE_DATABASE_PATH="$LITEFS_DIR/$CACHE_DATABASE_FILENAME"
+ENV INTERNAL_PORT="8080"
+ENV PORT="8081"
+ENV NODE_ENV="production"
+# For WAL support: https://github.com/prisma/prisma-engines/issues/4675#issuecomment-1914383246
+ENV PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK = "1"
+
+# add shortcut for connecting to database CLI
+RUN echo "#!/bin/sh\nset -x\nsqlite3 \$DATABASE_URL" > /usr/local/bin/database-cli && chmod +x /usr/local/bin/database-cli
+
+WORKDIR /myapp
+
+# Generate random value and save it to .env file which will be loaded by dotenv
+RUN INTERNAL_COMMAND_TOKEN=$(openssl rand -hex 32) && \
+ echo "INTERNAL_COMMAND_TOKEN=$INTERNAL_COMMAND_TOKEN" > .env
+
+COPY --from=production-deps /myapp/node_modules /myapp/node_modules
+COPY --from=build /myapp/node_modules/.prisma /myapp/node_modules/.prisma
+
+COPY --from=build /myapp/server-build /myapp/server-build
+COPY --from=build /myapp/build /myapp/build
+COPY --from=build /myapp/package.json /myapp/package.json
+COPY --from=build /myapp/prisma /myapp/prisma
+COPY --from=build /myapp/app/components/ui/icons /myapp/app/components/ui/icons
+
+# prepare for litefs
+COPY --from=flyio/litefs:0.5.11 /usr/local/bin/litefs /usr/local/bin/litefs
+ADD other/litefs.yml /etc/litefs.yml
+RUN mkdir -p /data ${LITEFS_DIR}
+
+ADD . .
+
+CMD ["litefs", "mount"]
diff --git a/other/Dockerfile.dockerignore b/other/Dockerfile.dockerignore
new file mode 100644
index 0000000..6e18765
--- /dev/null
+++ b/other/Dockerfile.dockerignore
@@ -0,0 +1,9 @@
+# This file is moved to the root directory before building the image
+
+/node_modules
+*.log
+.DS_Store
+.env
+/.cache
+/public/build
+/build
diff --git a/other/README.md b/other/README.md
new file mode 100644
index 0000000..a934f46
--- /dev/null
+++ b/other/README.md
@@ -0,0 +1,9 @@
+# Other
+
+The "other" directory is where we put stuff that doesn't really have a place,
+but we don't want in the root of the project. In fact, we want to move as much
+stuff here from the root as possible. The only things that should stay in the
+root directory are those things that have to stay in the root for most editor
+and other tool integrations (like most configuration files sadly). Maybe one day
+we can convince tools to adopt a new `.config` directory in the future. Until
+then, we've got this `./other` directory to keep things cleaner.
diff --git a/other/build-icons.ts b/other/build-icons.ts
new file mode 100644
index 0000000..ccaaf1a
--- /dev/null
+++ b/other/build-icons.ts
@@ -0,0 +1,153 @@
+import * as path from 'node:path'
+import { $ } from 'execa'
+import fsExtra from 'fs-extra'
+import { glob } from 'glob'
+import { parse } from 'node-html-parser'
+
+const cwd = process.cwd()
+const inputDir = path.join(cwd, 'other', 'svg-icons')
+const inputDirRelative = path.relative(cwd, inputDir)
+const outputDir = path.join(cwd, 'app', 'components', 'ui', 'icons')
+await fsExtra.ensureDir(outputDir)
+
+const files = glob
+ .sync('**/*.svg', {
+ cwd: inputDir,
+ })
+ .sort((a, b) => a.localeCompare(b))
+
+const shouldVerboseLog = process.argv.includes('--log=verbose')
+const logVerbose = shouldVerboseLog ? console.log : () => {}
+
+if (files.length === 0) {
+ console.log(`No SVG files found in ${inputDirRelative}`)
+} else {
+ await generateIconFiles()
+}
+
+async function generateIconFiles() {
+ const spriteFilepath = path.join(outputDir, 'sprite.svg')
+ const typeOutputFilepath = path.join(outputDir, 'name.d.ts')
+ const currentSprite = await fsExtra
+ .readFile(spriteFilepath, 'utf8')
+ .catch(() => '')
+ const currentTypes = await fsExtra
+ .readFile(typeOutputFilepath, 'utf8')
+ .catch(() => '')
+
+ const iconNames = files.map((file) => iconName(file))
+
+ const spriteUpToDate = iconNames.every((name) =>
+ currentSprite.includes(`id=${name}`),
+ )
+ const typesUpToDate = iconNames.every((name) =>
+ currentTypes.includes(`"${name}"`),
+ )
+
+ if (spriteUpToDate && typesUpToDate) {
+ logVerbose(`Icons are up to date`)
+ return
+ }
+
+ logVerbose(`Generating sprite for ${inputDirRelative}`)
+
+ const spriteChanged = await generateSvgSprite({
+ files,
+ inputDir,
+ outputPath: spriteFilepath,
+ })
+
+ for (const file of files) {
+ logVerbose('â
', file)
+ }
+ logVerbose(`Saved to ${path.relative(cwd, spriteFilepath)}`)
+
+ const stringifiedIconNames = iconNames.map((name) => JSON.stringify(name))
+
+ const typeOutputContent = `// This file is generated by npm run build:icons
+
+export type IconName =
+\t| ${stringifiedIconNames.join('\n\t| ')};
+`
+ const typesChanged = await writeIfChanged(
+ typeOutputFilepath,
+ typeOutputContent,
+ )
+
+ logVerbose(`Manifest saved to ${path.relative(cwd, typeOutputFilepath)}`)
+
+ const readmeChanged = await writeIfChanged(
+ path.join(outputDir, 'README.md'),
+ `# Icons
+
+This directory contains SVG icons that are used by the app.
+
+Everything in this directory is generated by \`npm run build:icons\`.
+`,
+ )
+
+ if (spriteChanged || typesChanged || readmeChanged) {
+ console.log(`Generated ${files.length} icons`)
+ }
+}
+
+function iconName(file: string) {
+ return file.replace(/\.svg$/, '')
+}
+
+/**
+ * Creates a single SVG file that contains all the icons
+ */
+async function generateSvgSprite({
+ files,
+ inputDir,
+ outputPath,
+}: {
+ files: string[]
+ inputDir: string
+ outputPath: string
+}) {
+ // Each SVG becomes a symbol and we wrap them all in a single SVG
+ const symbols = await Promise.all(
+ files.map(async (file) => {
+ const input = await fsExtra.readFile(path.join(inputDir, file), 'utf8')
+ const root = parse(input)
+
+ const svg = root.querySelector('svg')
+ if (!svg) throw new Error('No SVG element found')
+
+ svg.tagName = 'symbol'
+ svg.setAttribute('id', iconName(file))
+ svg.removeAttribute('xmlns')
+ svg.removeAttribute('xmlns:xlink')
+ svg.removeAttribute('version')
+ svg.removeAttribute('width')
+ svg.removeAttribute('height')
+
+ return svg.toString().trim()
+ }),
+ )
+
+ const output = [
+ ``,
+ ``,
+ ``,
+ ``, // for semantics: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
+ ...symbols,
+ ` `,
+ ` `,
+ '', // trailing newline
+ ].join('\n')
+
+ return writeIfChanged(outputPath, output)
+}
+
+async function writeIfChanged(filepath: string, newContent: string) {
+ const currentContent = await fsExtra
+ .readFile(filepath, 'utf8')
+ .catch(() => '')
+ if (currentContent === newContent) return false
+ await fsExtra.writeFile(filepath, newContent, 'utf8')
+ await $`prettier --write ${filepath} --ignore-unknown`
+ return true
+}
diff --git a/other/build-server.ts b/other/build-server.ts
new file mode 100644
index 0000000..896b0f6
--- /dev/null
+++ b/other/build-server.ts
@@ -0,0 +1,50 @@
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+import esbuild from 'esbuild'
+import fsExtra from 'fs-extra'
+import { globSync } from 'glob'
+
+const pkg = fsExtra.readJsonSync(path.join(process.cwd(), 'package.json'))
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const here = (...s: Array) => path.join(__dirname, ...s)
+const globsafe = (s: string) => s.replace(/\\/g, '/')
+
+const allFiles = globSync(globsafe(here('../server/**/*.*')), {
+ ignore: [
+ 'server/dev-server.js', // for development only
+ '**/tsconfig.json',
+ '**/eslint*',
+ '**/__tests__/**',
+ ],
+})
+
+const entries = []
+for (const file of allFiles) {
+ if (/\.(ts|js|tsx|jsx)$/.test(file)) {
+ entries.push(file)
+ } else {
+ const dest = file.replace(here('../server'), here('../server-build'))
+ fsExtra.ensureDirSync(path.parse(dest).dir)
+ fsExtra.copySync(file, dest)
+ console.log(`copied: ${file.replace(`${here('../server')}/`, '')}`)
+ }
+}
+
+console.log()
+console.log('building...')
+
+esbuild
+ .build({
+ entryPoints: entries,
+ outdir: here('../server-build'),
+ target: [`node${pkg.engines.node}`],
+ platform: 'node',
+ sourcemap: true,
+ format: 'esm',
+ logLevel: 'info',
+ })
+ .catch((error: unknown) => {
+ console.error(error)
+ process.exit(1)
+ })
diff --git a/other/litefs.yml b/other/litefs.yml
new file mode 100644
index 0000000..8ccc5bb
--- /dev/null
+++ b/other/litefs.yml
@@ -0,0 +1,43 @@
+# Documented example: https://github.com/superfly/litefs/blob/dec5a7353292068b830001bd2df4830e646f6a2f/cmd/litefs/etc/litefs.yml
+fuse:
+ # Required. This is the mount directory that applications will
+ # use to access their SQLite databases.
+ dir: '${LITEFS_DIR}'
+
+data:
+ # Path to internal data storage.
+ dir: '/data/litefs'
+
+proxy:
+ # matches the internal_port in fly.toml
+ addr: ':${INTERNAL_PORT}'
+ target: 'localhost:${PORT}'
+ db: '${DATABASE_FILENAME}'
+
+# The lease section specifies how the cluster will be managed. We're using the
+# "consul" lease type so that our application can dynamically change the primary.
+#
+# These environment variables will be available in your Fly.io application.
+lease:
+ type: 'consul'
+ candidate: ${FLY_REGION == PRIMARY_REGION}
+ promote: true
+ advertise-url: 'http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202'
+
+ consul:
+ url: '${FLY_CONSUL_URL}'
+ key: 'epic-stack-litefs/${FLY_APP_NAME}'
+
+exec:
+ - cmd: npx prisma migrate deploy
+ if-candidate: true
+
+ # Set the journal mode for the database to WAL. This reduces concurrency deadlock issues
+ - cmd: sqlite3 $DATABASE_PATH "PRAGMA journal_mode = WAL;"
+ if-candidate: true
+
+ # Set the journal mode for the cache to WAL. This reduces concurrency deadlock issues
+ - cmd: sqlite3 $CACHE_DATABASE_PATH "PRAGMA journal_mode = WAL;"
+ if-candidate: true
+
+ - cmd: npm start
diff --git a/other/sly/sly.json b/other/sly/sly.json
new file mode 100644
index 0000000..4f109e7
--- /dev/null
+++ b/other/sly/sly.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://sly-cli.fly.dev/registry/config.json",
+ "libraries": [
+ {
+ "name": "@radix-ui/icons",
+ "directory": "./other/svg-icons",
+ "postinstall": ["npm", "run", "build:icons"],
+ "transformers": ["transform-icon.ts"]
+ }
+ ]
+}
diff --git a/other/sly/transform-icon.ts b/other/sly/transform-icon.ts
new file mode 100644
index 0000000..8100773
--- /dev/null
+++ b/other/sly/transform-icon.ts
@@ -0,0 +1,19 @@
+import { type Meta } from '@sly-cli/sly'
+
+/**
+ * @type {import('@sly-cli/sly/dist').Transformer}
+ */
+export default function transformIcon(input: string, meta: Meta) {
+ input = prependLicenseInfo(input, meta)
+
+ return input
+}
+
+function prependLicenseInfo(input: string, meta: Meta): string {
+ return [
+ ``,
+ ``,
+ ``,
+ input,
+ ].join('\n')
+}
diff --git a/other/svg-icons/README.md b/other/svg-icons/README.md
new file mode 100644
index 0000000..a9be9dd
--- /dev/null
+++ b/other/svg-icons/README.md
@@ -0,0 +1,11 @@
+# Icons
+
+These icons were downloaded from https://icons.radix-ui.com/ which is licensed
+under MIT: https://github.com/radix-ui/icons/blob/master/LICENSE
+
+It's important that you only add icons to this directory that the application
+actually needs as there's no "tree-shaking" for sprites. If you wish to manually
+split up your SVG sprite into multiple files, you'll need to update the
+`build-icons.ts` script to do that.
+
+Run `npm run build:icons` to update the sprite.
diff --git a/other/svg-icons/arrow-left.svg b/other/svg-icons/arrow-left.svg
new file mode 100644
index 0000000..d59c7a6
--- /dev/null
+++ b/other/svg-icons/arrow-left.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/arrow-right.svg b/other/svg-icons/arrow-right.svg
new file mode 100644
index 0000000..2c3424a
--- /dev/null
+++ b/other/svg-icons/arrow-right.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/avatar.svg b/other/svg-icons/avatar.svg
new file mode 100644
index 0000000..14acc3d
--- /dev/null
+++ b/other/svg-icons/avatar.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/camera.svg b/other/svg-icons/camera.svg
new file mode 100644
index 0000000..c5f1d35
--- /dev/null
+++ b/other/svg-icons/camera.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/check.svg b/other/svg-icons/check.svg
new file mode 100644
index 0000000..e057a8b
--- /dev/null
+++ b/other/svg-icons/check.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/clock.svg b/other/svg-icons/clock.svg
new file mode 100644
index 0000000..630c19b
--- /dev/null
+++ b/other/svg-icons/clock.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/cross-1.svg b/other/svg-icons/cross-1.svg
new file mode 100644
index 0000000..b94ccfe
--- /dev/null
+++ b/other/svg-icons/cross-1.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/dots-horizontal.svg b/other/svg-icons/dots-horizontal.svg
new file mode 100644
index 0000000..fa7758f
--- /dev/null
+++ b/other/svg-icons/dots-horizontal.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/other/svg-icons/download.svg b/other/svg-icons/download.svg
new file mode 100644
index 0000000..c5a617b
--- /dev/null
+++ b/other/svg-icons/download.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/other/svg-icons/envelope-closed.svg b/other/svg-icons/envelope-closed.svg
new file mode 100644
index 0000000..6a9d3f0
--- /dev/null
+++ b/other/svg-icons/envelope-closed.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/other/svg-icons/exit.svg b/other/svg-icons/exit.svg
new file mode 100644
index 0000000..292f94d
--- /dev/null
+++ b/other/svg-icons/exit.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/file-text.svg b/other/svg-icons/file-text.svg
new file mode 100644
index 0000000..5fe1b7e
--- /dev/null
+++ b/other/svg-icons/file-text.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/github-logo.svg b/other/svg-icons/github-logo.svg
new file mode 100644
index 0000000..7fbb0a9
--- /dev/null
+++ b/other/svg-icons/github-logo.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/other/svg-icons/laptop.svg b/other/svg-icons/laptop.svg
new file mode 100644
index 0000000..0297959
--- /dev/null
+++ b/other/svg-icons/laptop.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/link-2.svg b/other/svg-icons/link-2.svg
new file mode 100644
index 0000000..f36d6d9
--- /dev/null
+++ b/other/svg-icons/link-2.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/other/svg-icons/lock-closed.svg b/other/svg-icons/lock-closed.svg
new file mode 100644
index 0000000..677bdc7
--- /dev/null
+++ b/other/svg-icons/lock-closed.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/lock-open-1.svg b/other/svg-icons/lock-open-1.svg
new file mode 100644
index 0000000..789f9d4
--- /dev/null
+++ b/other/svg-icons/lock-open-1.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/magnifying-glass.svg b/other/svg-icons/magnifying-glass.svg
new file mode 100644
index 0000000..670396b
--- /dev/null
+++ b/other/svg-icons/magnifying-glass.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/moon.svg b/other/svg-icons/moon.svg
new file mode 100644
index 0000000..5df2660
--- /dev/null
+++ b/other/svg-icons/moon.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/pencil-1.svg b/other/svg-icons/pencil-1.svg
new file mode 100644
index 0000000..2695e8c
--- /dev/null
+++ b/other/svg-icons/pencil-1.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/pencil-2.svg b/other/svg-icons/pencil-2.svg
new file mode 100644
index 0000000..a249a09
--- /dev/null
+++ b/other/svg-icons/pencil-2.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/plus.svg b/other/svg-icons/plus.svg
new file mode 100644
index 0000000..5009fac
--- /dev/null
+++ b/other/svg-icons/plus.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/question-mark-circled.svg b/other/svg-icons/question-mark-circled.svg
new file mode 100644
index 0000000..c99757d
--- /dev/null
+++ b/other/svg-icons/question-mark-circled.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/other/svg-icons/reset.svg b/other/svg-icons/reset.svg
new file mode 100644
index 0000000..41c2e88
--- /dev/null
+++ b/other/svg-icons/reset.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/sun.svg b/other/svg-icons/sun.svg
new file mode 100644
index 0000000..b3891c9
--- /dev/null
+++ b/other/svg-icons/sun.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/trash.svg b/other/svg-icons/trash.svg
new file mode 100644
index 0000000..472954b
--- /dev/null
+++ b/other/svg-icons/trash.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/other/svg-icons/update.svg b/other/svg-icons/update.svg
new file mode 100644
index 0000000..c95c60d
--- /dev/null
+++ b/other/svg-icons/update.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..d204163
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,22909 @@
+{
+ "name": "publicare-ddc2",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "publicare-ddc2",
+ "dependencies": {
+ "@conform-to/react": "^1.1.5",
+ "@conform-to/zod": "^1.1.5",
+ "@epic-web/cachified": "^5.2.0",
+ "@epic-web/client-hints": "^1.3.2",
+ "@epic-web/invariant": "^1.0.0",
+ "@epic-web/remember": "^1.1.0",
+ "@epic-web/totp": "^1.1.2",
+ "@nasa-gcn/remix-seo": "^2.0.1",
+ "@paralleldrive/cuid2": "^2.2.2",
+ "@prisma/client": "^5.17.0",
+ "@radix-ui/react-checkbox": "^1.1.1",
+ "@radix-ui/react-dropdown-menu": "^2.1.1",
+ "@radix-ui/react-label": "^2.1.0",
+ "@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-toast": "^1.2.1",
+ "@radix-ui/react-tooltip": "^1.1.2",
+ "@react-email/components": "0.0.21",
+ "@remix-run/express": "2.10.3",
+ "@remix-run/node": "2.10.3",
+ "@remix-run/react": "2.10.3",
+ "@sentry/profiling-node": "^8.18.0",
+ "@sentry/remix": "^8.18.0",
+ "address": "^2.0.3",
+ "bcryptjs": "^2.4.3",
+ "better-sqlite3": "^11.1.2",
+ "chalk": "^5.3.0",
+ "class-variance-authority": "^0.7.0",
+ "close-with-grace": "^1.3.0",
+ "clsx": "^2.1.1",
+ "compression": "^1.7.4",
+ "cookie": "^0.6.0",
+ "cross-env": "^7.0.3",
+ "crypto-js": "^4.2.0",
+ "date-fns": "^3.6.0",
+ "dotenv": "^16.4.5",
+ "execa": "^9.3.0",
+ "express": "^4.19.2",
+ "express-rate-limit": "^7.3.1",
+ "get-port": "^7.1.0",
+ "glob": "^11.0.0",
+ "helmet": "^7.1.0",
+ "input-otp": "^1.2.4",
+ "intl-parse-accept-language": "^1.0.0",
+ "isbot": "^5.1.13",
+ "litefs-js": "^1.1.2",
+ "lru-cache": "^11.0.0",
+ "morgan": "^1.10.0",
+ "prisma": "^5.17.0",
+ "qrcode": "^1.5.3",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "remix-auth": "^3.7.0",
+ "remix-auth-github": "^1.7.0",
+ "remix-utils": "^7.6.0",
+ "set-cookie-parser": "^2.6.0",
+ "sonner": "^1.5.0",
+ "source-map-support": "^0.5.21",
+ "spin-delay": "^2.0.0",
+ "tailwind-merge": "^2.4.0",
+ "tailwindcss": "^3.4.6",
+ "tailwindcss-animate": "^1.0.7",
+ "tailwindcss-radix": "^3.0.3",
+ "vite-env-only": "^3.0.3",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@epic-web/config": "^1.12.0",
+ "@faker-js/faker": "^8.4.1",
+ "@playwright/test": "^1.45.2",
+ "@remix-run/dev": "2.10.3",
+ "@remix-run/testing": "2.10.3",
+ "@sentry/vite-plugin": "^2.21.1",
+ "@sly-cli/sly": "^1.13.0",
+ "@testing-library/dom": "^10.3.2",
+ "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/react": "^16.0.0",
+ "@testing-library/user-event": "^14.5.2",
+ "@total-typescript/ts-reset": "^0.5.1",
+ "@types/bcryptjs": "^2.4.6",
+ "@types/better-sqlite3": "^7.6.11",
+ "@types/compression": "^1.7.5",
+ "@types/cookie": "^0.6.0",
+ "@types/eslint": "^8.56.10",
+ "@types/express": "^4.17.21",
+ "@types/fs-extra": "^11.0.4",
+ "@types/glob": "^8.1.0",
+ "@types/morgan": "^1.9.9",
+ "@types/node": "^20.14.11",
+ "@types/qrcode": "^1.5.5",
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
+ "@types/set-cookie-parser": "^2.4.10",
+ "@types/source-map-support": "^0.5.10",
+ "@vitejs/plugin-react": "^4.3.1",
+ "@vitest/coverage-v8": "^2.0.3",
+ "autoprefixer": "^10.4.19",
+ "enforce-unique": "^1.3.0",
+ "esbuild": "^0.23.0",
+ "eslint": "^9.7.0",
+ "fs-extra": "^11.2.0",
+ "jsdom": "^24.1.0",
+ "msw": "2.3.1",
+ "node-html-parser": "^6.1.13",
+ "npm-run-all": "^4.1.5",
+ "prettier": "^3.3.3",
+ "prettier-plugin-sql": "^0.18.1",
+ "prettier-plugin-tailwindcss": "^0.6.5",
+ "remix-flat-routes": "^0.6.5",
+ "remix-ssg": "^0.0.8",
+ "serve": "^14.2.3",
+ "tsx": "^4.16.2",
+ "typescript": "^5.5.3",
+ "vite": "^5.3.4",
+ "vitest": "^2.0.3"
+ },
+ "engines": {
+ "node": "20"
+ }
+ },
+ "node_modules/@adobe/css-tools": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz",
+ "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz",
+ "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/highlight": "^7.24.6",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz",
+ "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz",
+ "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.24.6",
+ "@babel/generator": "^7.24.6",
+ "@babel/helper-compilation-targets": "^7.24.6",
+ "@babel/helper-module-transforms": "^7.24.6",
+ "@babel/helpers": "^7.24.6",
+ "@babel/parser": "^7.24.6",
+ "@babel/template": "^7.24.6",
+ "@babel/traverse": "^7.24.6",
+ "@babel/types": "^7.24.6",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz",
+ "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz",
+ "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz",
+ "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.24.6",
+ "@babel/helper-validator-option": "^7.24.6",
+ "browserslist": "^4.22.2",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "license": "ISC"
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz",
+ "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.24.6",
+ "@babel/helper-environment-visitor": "^7.24.6",
+ "@babel/helper-function-name": "^7.24.6",
+ "@babel/helper-member-expression-to-functions": "^7.24.6",
+ "@babel/helper-optimise-call-expression": "^7.24.6",
+ "@babel/helper-replace-supers": "^7.24.6",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6",
+ "@babel/helper-split-export-declaration": "^7.24.6",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz",
+ "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz",
+ "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.24.6",
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz",
+ "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz",
+ "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz",
+ "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz",
+ "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.24.6",
+ "@babel/helper-module-imports": "^7.24.6",
+ "@babel/helper-simple-access": "^7.24.6",
+ "@babel/helper-split-export-declaration": "^7.24.6",
+ "@babel/helper-validator-identifier": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz",
+ "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz",
+ "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz",
+ "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.24.6",
+ "@babel/helper-member-expression-to-functions": "^7.24.6",
+ "@babel/helper-optimise-call-expression": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz",
+ "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz",
+ "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz",
+ "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz",
+ "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz",
+ "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz",
+ "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz",
+ "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.24.6",
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz",
+ "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.24.6",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz",
+ "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==",
+ "license": "MIT",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-decorators": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.6.tgz",
+ "integrity": "sha512-gInH8LEqBp+wkwTVihCd/qf+4s28g81FZyvlIbAurHk9eSiItEKG7E0uNK2UdpgsD79aJVAW3R3c85h0YJ0jsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz",
+ "integrity": "sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz",
+ "integrity": "sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz",
+ "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.24.6",
+ "@babel/helper-plugin-utils": "^7.24.6",
+ "@babel/helper-simple-access": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.6.tgz",
+ "integrity": "sha512-FfZfHXtQ5jYPQsCRyLpOv2GeLIIJhs8aydpNh39vRDjhD411XcfWDni5i7OjP/Rs8GAtTn7sWFFELJSHqkIxYg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.6.tgz",
+ "integrity": "sha512-BQTBCXmFRreU3oTUXcGKuPOfXAGb1liNY4AvvFKsOBAJ89RKcTsIrSsnMYkj59fNa66OFKnSa4AJZfy5Y4B9WA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz",
+ "integrity": "sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.24.6",
+ "@babel/helper-create-class-features-plugin": "^7.24.6",
+ "@babel/helper-plugin-utils": "^7.24.6",
+ "@babel/plugin-syntax-typescript": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz",
+ "integrity": "sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.6",
+ "@babel/helper-validator-option": "^7.24.6",
+ "@babel/plugin-syntax-jsx": "^7.24.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.6",
+ "@babel/plugin-transform-typescript": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz",
+ "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==",
+ "license": "MIT",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz",
+ "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.24.6",
+ "@babel/parser": "^7.24.6",
+ "@babel/types": "^7.24.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz",
+ "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.24.6",
+ "@babel/generator": "^7.24.6",
+ "@babel/helper-environment-visitor": "^7.24.6",
+ "@babel/helper-function-name": "^7.24.6",
+ "@babel/helper-hoist-variables": "^7.24.6",
+ "@babel/helper-split-export-declaration": "^7.24.6",
+ "@babel/parser": "^7.24.6",
+ "@babel/types": "^7.24.6",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz",
+ "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.24.6",
+ "@babel/helper-validator-identifier": "^7.24.6",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@bundled-es-modules/cookie": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz",
+ "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cookie": "^0.5.0"
+ }
+ },
+ "node_modules/@bundled-es-modules/cookie/node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/@bundled-es-modules/statuses": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz",
+ "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "statuses": "^2.0.1"
+ }
+ },
+ "node_modules/@conform-to/dom": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@conform-to/dom/-/dom-1.1.5.tgz",
+ "integrity": "sha512-tWI3YxWvDaZFSl4QN8Y0WbgBxsWEfcTrSMtKic3YTt/hGVJXjQ8qURBdsJXudzJ38zwAr5GhpLWmyI6BbG9+gA==",
+ "license": "MIT"
+ },
+ "node_modules/@conform-to/react": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@conform-to/react/-/react-1.1.5.tgz",
+ "integrity": "sha512-QyzJ8SIazHmez7qkMffypICDBwU+Ht5TPe+C4MTP2dro0N0Hu6LsfLq7mMWFJyAJ7IYxT1BMzfoFj28jheIIOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@conform-to/dom": "1.1.5"
+ },
+ "peerDependencies": {
+ "react": ">=18"
+ }
+ },
+ "node_modules/@conform-to/zod": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@conform-to/zod/-/zod-1.1.5.tgz",
+ "integrity": "sha512-ho/742wgfTWf2u5tKo4GT88xcKcvTOCDPOi4o1WEmePPmJNP5ezeMQSKSdKdS0rFinZl9ZTH8gV5FQUNPHAA7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@conform-to/dom": "1.1.5"
+ },
+ "peerDependencies": {
+ "zod": "^3.21.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
+ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@epic-web/cachified": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@epic-web/cachified/-/cachified-5.2.0.tgz",
+ "integrity": "sha512-E/2LdIhS/wcn3ykV+u5xbTFahKtzReO0k4/cVtE7KBYiLCgR6bPRmlDUuyfWhbZX3zOmK+6OL7qdHkvgCWwSiA==",
+ "license": "MIT"
+ },
+ "node_modules/@epic-web/client-hints": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@epic-web/client-hints/-/client-hints-1.3.3.tgz",
+ "integrity": "sha512-ww6WMT0O7P4r6yNyGa9JOSeMP8E5TLGbSprkoteNjxlueZjVIXxA2TGsO5cnkcCsEFhkDATJKzmiHv+EbUUOrw==",
+ "license": "MIT"
+ },
+ "node_modules/@epic-web/config": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/@epic-web/config/-/config-1.12.0.tgz",
+ "integrity": "sha512-hEwVh+GTp97mR8fURLQ/mmwNhvRl7OivCJBE/Gl6TSSxDYO4emyvjD5+sqLgbDQenHde96vqPyf6UsO7ForAOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint/compat": "^1.1.0",
+ "@total-typescript/ts-reset": "^0.5.1",
+ "eslint-plugin-import-x": "^0.5.1",
+ "eslint-plugin-jest-dom": "^5.4.0",
+ "eslint-plugin-react": "^7.34.2",
+ "eslint-plugin-react-hooks": "^4.6.2",
+ "eslint-plugin-testing-library": "^6.2.2",
+ "eslint-plugin-vitest": "^0.5.4",
+ "globals": "^15.4.0",
+ "prettier-plugin-tailwindcss": "^0.6.1",
+ "tslib": "^2.6.3",
+ "typescript-eslint": "^8.0.0-alpha.20"
+ }
+ },
+ "node_modules/@epic-web/invariant": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
+ "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
+ "license": "MIT"
+ },
+ "node_modules/@epic-web/remember": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@epic-web/remember/-/remember-1.1.0.tgz",
+ "integrity": "sha512-FIhO7PFUVEbcnrJOtom8gb4GXog4Z44n4Jxwmw2nkKt4mx8I/q/d0O4tMabjYndM1QX2oXvRYzpZxtP61s2P5A==",
+ "license": "MIT"
+ },
+ "node_modules/@epic-web/totp": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@epic-web/totp/-/totp-1.1.2.tgz",
+ "integrity": "sha512-ngw0+NjNgZ1ikmascnQWfut7dj0cuWqKwDM7m2w7JoOXHZCR0C5cx2aUPIl8oHOO2DQzkI6yaJLoc1bMDOn/oQ==",
+ "license": "MIT",
+ "dependencies": {
+ "thirty-two": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz",
+ "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz",
+ "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz",
+ "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz",
+ "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz",
+ "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz",
+ "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz",
+ "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz",
+ "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz",
+ "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz",
+ "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz",
+ "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz",
+ "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz",
+ "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz",
+ "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz",
+ "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz",
+ "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz",
+ "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz",
+ "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz",
+ "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz",
+ "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz",
+ "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz",
+ "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz",
+ "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz",
+ "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
+ "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/compat": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz",
+ "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz",
+ "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.4",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
+ "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz",
+ "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz",
+ "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@faker-js/faker": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz",
+ "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fakerjs"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0",
+ "npm": ">=6.14.13"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz",
+ "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.4"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz",
+ "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.6.0",
+ "@floating-ui/utils": "^0.2.4"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz",
+ "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz",
+ "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==",
+ "license": "MIT"
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz",
+ "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@inquirer/confirm": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.8.tgz",
+ "integrity": "sha512-f3INZ+ca4dQdn+MQiq1yP/mOIR/Oc8BLRYuDh6ciToWd6z4W8yArfzjBCMQ0BPY8PcJKwZxGIt8Z6yNT32eSTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^8.2.1",
+ "@inquirer/type": "^1.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/core": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-8.2.1.tgz",
+ "integrity": "sha512-TIcuQMn2qrtyYe0j136UpHeYpk7AcR/trKeT/7YY0vRgcS9YSfJuQ2+PudPhSofLLsHNnRYAHScQCcVZrJkMqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/figures": "^1.0.2",
+ "@inquirer/type": "^1.3.2",
+ "@types/mute-stream": "^0.0.4",
+ "@types/node": "^20.12.12",
+ "@types/wrap-ansi": "^3.0.0",
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^4.1.2",
+ "cli-spinners": "^2.9.2",
+ "cli-width": "^4.1.0",
+ "mute-stream": "^1.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@inquirer/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@inquirer/core/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/figures": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.2.tgz",
+ "integrity": "sha512-4F1MBwVr3c/m4bAUef6LgkvBfSjzwH+OfldgHqcuacWwSUetFebM2wi58WfG9uk1rR98U6GwLed4asLJbwdV5w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/type": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.3.2.tgz",
+ "integrity": "sha512-5Frickan9c89QbPkSu6I6y8p+9eR6hZkdPahGmNDsTFX8FHLPAozyzCZMKUeW8FyYwnlCKUjqIEqxY+UctARiw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@jspm/core": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@jspm/core/-/core-2.0.1.tgz",
+ "integrity": "sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==",
+ "dev": true
+ },
+ "node_modules/@mdx-js/mdx": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.3.0.tgz",
+ "integrity": "sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/mdx": "^2.0.0",
+ "estree-util-build-jsx": "^2.0.0",
+ "estree-util-is-identifier-name": "^2.0.0",
+ "estree-util-to-js": "^1.1.0",
+ "estree-walker": "^3.0.0",
+ "hast-util-to-estree": "^2.0.0",
+ "markdown-extensions": "^1.0.0",
+ "periscopic": "^3.0.0",
+ "remark-mdx": "^2.0.0",
+ "remark-parse": "^10.0.0",
+ "remark-rehype": "^10.0.0",
+ "unified": "^10.0.0",
+ "unist-util-position-from-estree": "^1.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "unist-util-visit": "^4.0.0",
+ "vfile": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@mswjs/cookies": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-1.1.0.tgz",
+ "integrity": "sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@mswjs/interceptors": {
+ "version": "0.29.1",
+ "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz",
+ "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@open-draft/deferred-promise": "^2.2.0",
+ "@open-draft/logger": "^0.3.0",
+ "@open-draft/until": "^2.0.0",
+ "is-node-process": "^1.2.0",
+ "outvariant": "^1.2.1",
+ "strict-event-emitter": "^0.5.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@nasa-gcn/remix-seo": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@nasa-gcn/remix-seo/-/remix-seo-2.0.1.tgz",
+ "integrity": "sha512-g9biDdYfsdFBnOU7lM+7vPGEXSEMRnWmfVLDQ98pT0PnTT/O3pFuA+s3DA0Mj9IwnAq9IcLs2Wee/aL6fvEA+A==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.21"
+ },
+ "peerDependencies": {
+ "@remix-run/react": "^1.0.0 || ^2.0.0",
+ "@remix-run/server-runtime": "^1.0.0 || ^2.0.0"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
+ "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz",
+ "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/git": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz",
+ "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@npmcli/promise-spawn": "^6.0.0",
+ "lru-cache": "^7.4.4",
+ "npm-pick-manifest": "^8.0.0",
+ "proc-log": "^3.0.0",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@npmcli/package-json": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-4.0.1.tgz",
+ "integrity": "sha512-lRCEGdHZomFsURroh522YvA/2cVb9oPIJrjHanCJZkiasz1BzcnLr3tBJhlV7S86MBJBuAQ33is2D60YitZL2Q==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@npmcli/git": "^4.1.0",
+ "glob": "^10.2.2",
+ "hosted-git-info": "^6.1.1",
+ "json-parse-even-better-errors": "^3.0.0",
+ "normalize-package-data": "^5.0.0",
+ "proc-log": "^3.0.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/package-json/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@npmcli/package-json/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/@npmcli/package-json/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@npmcli/package-json/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@npmcli/promise-spawn": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz",
+ "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@one-ini/wasm": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
+ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
+ "license": "MIT"
+ },
+ "node_modules/@open-draft/deferred-promise": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
+ "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@open-draft/logger": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz",
+ "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-node-process": "^1.2.0",
+ "outvariant": "^1.4.0"
+ }
+ },
+ "node_modules/@open-draft/until": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz",
+ "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@opentelemetry/api": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
+ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/api-logs": {
+ "version": "0.52.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz",
+ "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/context-async-hooks": {
+ "version": "1.25.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.25.1.tgz",
+ "integrity": "sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/core": {
+ "version": "1.25.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.25.1.tgz",
+ "integrity": "sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.25.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation": {
+ "version": "0.52.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz",
+ "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.52.1",
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "^1.8.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-connect": {
+ "version": "0.38.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.38.0.tgz",
+ "integrity": "sha512-2/nRnx3pjYEmdPIaBwtgtSviTKHWnDZN3R+TkRUnhIVrvBKVcq+I5B2rtd6mr6Fe9cHlZ9Ojcuh7pkNh/xdWWg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "@types/connect": "3.4.36"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-express": {
+ "version": "0.41.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.41.0.tgz",
+ "integrity": "sha512-/B7fbMdaf3SYe5f1P973tkqd6s7XZirjpfkoJ63E7nltU30qmlgm9tY5XwZOzAFI0rHS9tbrFI2HFPAvQUFe/A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fastify": {
+ "version": "0.38.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.38.0.tgz",
+ "integrity": "sha512-HBVLpTSYpkQZ87/Df3N0gAw7VzYZV3n28THIBrJWfuqw3Or7UqdhnjeuMIPQ04BKk3aZc0cWn2naSQObbh5vXw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-graphql": {
+ "version": "0.42.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.42.0.tgz",
+ "integrity": "sha512-N8SOwoKL9KQSX7z3gOaw5UaTeVQcfDO1c21csVHnmnmGUoqsXbArK2B8VuwPWcv6/BC/i3io+xTo7QGRZ/z28Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-hapi": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.40.0.tgz",
+ "integrity": "sha512-8U/w7Ifumtd2bSN1OLaSwAAFhb9FyqWUki3lMMB0ds+1+HdSxYBe9aspEJEgvxAqOkrQnVniAPTEGf1pGM7SOw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http": {
+ "version": "0.52.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.52.1.tgz",
+ "integrity": "sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/instrumentation": "0.52.1",
+ "@opentelemetry/semantic-conventions": "1.25.1",
+ "semver": "^7.5.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-ioredis": {
+ "version": "0.42.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.42.0.tgz",
+ "integrity": "sha512-P11H168EKvBB9TUSasNDOGJCSkpT44XgoM6d3gRIWAa9ghLpYhl0uRkS8//MqPzcJVHr3h3RmfXIpiYLjyIZTw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/redis-common": "^0.36.2",
+ "@opentelemetry/semantic-conventions": "^1.23.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-koa": {
+ "version": "0.42.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.42.0.tgz",
+ "integrity": "sha512-H1BEmnMhho8o8HuNRq5zEI4+SIHDIglNB7BPKohZyWG4fWNuR7yM4GTlR01Syq21vODAS7z5omblScJD/eZdKw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongodb": {
+ "version": "0.46.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.46.0.tgz",
+ "integrity": "sha512-VF/MicZ5UOBiXrqBslzwxhN7TVqzu1/LN/QDpkskqM0Zm0aZ4CVRbUygL8d7lrjLn15x5kGIe8VsSphMfPJzlA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/sdk-metrics": "^1.9.1",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongoose": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.40.0.tgz",
+ "integrity": "sha512-niRi5ZUnkgzRhIGMOozTyoZIvJKNJyhijQI4nF4iFSb+FUx2v5fngfR+8XLmdQAO7xmsD8E5vEGdDVYVtKbZew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.40.0.tgz",
+ "integrity": "sha512-d7ja8yizsOCNMYIJt5PH/fKZXjb/mS48zLROO4BzZTtDfhNCl2UM/9VIomP2qkGIFVouSJrGr/T00EzY7bPtKA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "@types/mysql": "2.15.22"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql2": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.40.0.tgz",
+ "integrity": "sha512-0xfS1xcqUmY7WE1uWjlmI67Xg3QsSUlNT+AcXHeA4BDUPwZtWqF4ezIwLgpVZfHOnkAEheqGfNSWd1PIu3Wnfg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "@opentelemetry/sql-common": "^0.40.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-nestjs-core": {
+ "version": "0.39.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.39.0.tgz",
+ "integrity": "sha512-mewVhEXdikyvIZoMIUry8eb8l3HUjuQjSjVbmLVTt4NQi35tkpnHQrG9bTRBrl3403LoWZ2njMPJyg4l6HfKvA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.23.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pg": {
+ "version": "0.43.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.43.0.tgz",
+ "integrity": "sha512-og23KLyoxdnAeFs1UWqzSonuCkePUzCX30keSYigIzJe/6WSYA8rnEI5lobcxPEzg+GcU06J7jzokuEHbjVJNw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "@opentelemetry/sql-common": "^0.40.1",
+ "@types/pg": "8.6.1",
+ "@types/pg-pool": "2.0.4"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis-4": {
+ "version": "0.41.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.41.0.tgz",
+ "integrity": "sha512-H7IfGTqW2reLXqput4yzAe8YpDC0fmVNal95GHMLOrS89W+qWUKIqxolSh63hJyfmwPSFwXASzj7wpSk8Az+Dg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.52.0",
+ "@opentelemetry/redis-common": "^0.36.2",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/redis-common": {
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz",
+ "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/resources": {
+ "version": "1.25.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.25.1.tgz",
+ "integrity": "sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/semantic-conventions": "1.25.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-metrics": {
+ "version": "1.25.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.25.1.tgz",
+ "integrity": "sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/resources": "1.25.1",
+ "lodash.merge": "^4.6.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "1.25.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz",
+ "integrity": "sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.25.1",
+ "@opentelemetry/resources": "1.25.1",
+ "@opentelemetry/semantic-conventions": "1.25.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.25.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz",
+ "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/sql-common": {
+ "version": "0.40.1",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz",
+ "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0"
+ }
+ },
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
+ "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==",
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "^1.1.5"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@playwright/test": {
+ "version": "1.45.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.2.tgz",
+ "integrity": "sha512-JxG9eq92ET75EbVi3s+4sYbcG7q72ECeZNbdBlaMkGcNbiDQ4cAi8U2QP5oKkOx+1gpaiL1LDStmzCaEM1Z6fQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright": "1.45.2"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@prisma/client": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.17.0.tgz",
+ "integrity": "sha512-N2tnyKayT0Zf7mHjwEyE8iG7FwTmXDHFZ1GnNhQp0pJUObsuel4ZZ1XwfuAYkq5mRIiC/Kot0kt0tGCfLJ70Jw==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16.13"
+ },
+ "peerDependencies": {
+ "prisma": "*"
+ },
+ "peerDependenciesMeta": {
+ "prisma": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@prisma/debug": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.17.0.tgz",
+ "integrity": "sha512-l7+AteR3P8FXiYyo496zkuoiJ5r9jLQEdUuxIxNCN1ud8rdbH3GTxm+f+dCyaSv9l9WY+29L9czaVRXz9mULfg==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/engines": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.17.0.tgz",
+ "integrity": "sha512-+r+Nf+JP210Jur+/X8SIPLtz+uW9YA4QO5IXA+KcSOBe/shT47bCcRMTYCbOESw3FFYFTwe7vU6KTWHKPiwvtg==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.17.0",
+ "@prisma/engines-version": "5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053",
+ "@prisma/fetch-engine": "5.17.0",
+ "@prisma/get-platform": "5.17.0"
+ }
+ },
+ "node_modules/@prisma/engines-version": {
+ "version": "5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053",
+ "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053.tgz",
+ "integrity": "sha512-tUuxZZysZDcrk5oaNOdrBnnkoTtmNQPkzINFDjz7eG6vcs9AVDmA/F6K5Plsb2aQc/l5M2EnFqn3htng9FA4hg==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@prisma/fetch-engine": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.17.0.tgz",
+ "integrity": "sha512-ESxiOaHuC488ilLPnrv/tM2KrPhQB5TRris/IeIV4ZvUuKeaicCl4Xj/JCQeG9IlxqOgf1cCg5h5vAzlewN91Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.17.0",
+ "@prisma/engines-version": "5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053",
+ "@prisma/get-platform": "5.17.0"
+ }
+ },
+ "node_modules/@prisma/get-platform": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.17.0.tgz",
+ "integrity": "sha512-UlDgbRozCP1rfJ5Tlkf3Cnftb6srGrEQ4Nm3og+1Se2gWmCZ0hmPIi+tQikGDUVLlvOWx3Gyi9LzgRP+HTXV9w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/debug": "5.17.0"
+ }
+ },
+ "node_modules/@prisma/instrumentation": {
+ "version": "5.16.1",
+ "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-5.16.1.tgz",
+ "integrity": "sha512-4m5gRFWnQb8s/yTyGbMZkL7A5uJgqOWcWJxapwcAD0T0kh5sGPEVSQl/zTQvE9aduXhFAxOtC3gO+R8Hb5xO1Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.8",
+ "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0",
+ "@opentelemetry/sdk-trace-base": "^1.22"
+ }
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
+ "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==",
+ "license": "MIT"
+ },
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
+ "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-checkbox": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz",
+ "integrity": "sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-presence": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
+ "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-slot": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
+ "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
+ "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
+ "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz",
+ "integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-escape-keydown": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz",
+ "integrity": "sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-menu": "2.1.1",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz",
+ "integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz",
+ "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
+ "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz",
+ "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.1.tgz",
+ "integrity": "sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-collection": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.0",
+ "@radix-ui/react-focus-guards": "1.1.0",
+ "@radix-ui/react-focus-scope": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-popper": "1.2.0",
+ "@radix-ui/react-portal": "1.1.1",
+ "@radix-ui/react-presence": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-roving-focus": "1.1.0",
+ "@radix-ui/react-slot": "1.1.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "aria-hidden": "^1.1.1",
+ "react-remove-scroll": "2.5.7"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
+ "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-use-rect": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0",
+ "@radix-ui/rect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz",
+ "integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz",
+ "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
+ "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
+ "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-collection": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
+ "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-toast": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.1.tgz",
+ "integrity": "sha512-5trl7piMXcZiCq7MW6r8YYmu0bK5qDpTWz+FdEPdKyft2UixkspheYbjbrLXVN5NGKHFbOP7lm8eD0biiSqZqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-collection": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.0",
+ "@radix-ui/react-portal": "1.1.1",
+ "@radix-ui/react-presence": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.2.tgz",
+ "integrity": "sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-dismissable-layer": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-popper": "1.2.0",
+ "@radix-ui/react-portal": "1.1.1",
+ "@radix-ui/react-presence": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-slot": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-visually-hidden": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
+ "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz",
+ "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
+ "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
+ "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz",
+ "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
+ "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
+ "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz",
+ "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
+ "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==",
+ "license": "MIT"
+ },
+ "node_modules/@react-email/body": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/body/-/body-0.0.8.tgz",
+ "integrity": "sha512-gqdkNYlIaIw0OdpWu8KjIcQSIFvx7t2bZpXVxMMvBS859Ia1+1X3b5RNbjI3S1ZqLddUf7owOHkO4MiXGE+nxg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/button": {
+ "version": "0.0.15",
+ "resolved": "https://registry.npmjs.org/@react-email/button/-/button-0.0.15.tgz",
+ "integrity": "sha512-9Zi6SO3E8PoHYDfcJTecImiHLyitYWmIRs0HE3Ogra60ZzlWP2EXu+AZqwQnhXuq+9pbgwBWNWxB5YPetNPTNA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/code-block": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@react-email/code-block/-/code-block-0.0.5.tgz",
+ "integrity": "sha512-mmInpZsSIkNaYC1y40/S0XXrIqbTzrpllP6J1JMJuDOBG8l5T7pNl4V+gwfsSTvy9hVsuzQFmhHK8kVb1UXv3A==",
+ "license": "MIT",
+ "dependencies": {
+ "prismjs": "1.29.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/code-inline": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@react-email/code-inline/-/code-inline-0.0.2.tgz",
+ "integrity": "sha512-0cmgbbibFeOJl0q04K9jJlPDuJ+SEiX/OG6m3Ko7UOkG3TqjRD8Dtvkij6jNDVfUh/zESpqJCP2CxrCLLMUjdA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/column": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/@react-email/column/-/column-0.0.10.tgz",
+ "integrity": "sha512-MnP8Mnwipr0X3XtdD6jMLckb0sI5/IlS6Kl/2F6/rsSWBJy5Gg6nizlekTdkwDmy0kNSe3/1nGU0Zqo98pl63Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/components": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/@react-email/components/-/components-0.0.21.tgz",
+ "integrity": "sha512-fwGfH7FF+iuq+IdPcbEO5HoF0Pakk9big+fFW9+3kiyvbSNuo8Io1rhPTMLd8q41XomN4g7mgWovdAeS/8PHrA==",
+ "license": "MIT",
+ "dependencies": {
+ "@react-email/body": "0.0.8",
+ "@react-email/button": "0.0.15",
+ "@react-email/code-block": "0.0.5",
+ "@react-email/code-inline": "0.0.2",
+ "@react-email/column": "0.0.10",
+ "@react-email/container": "0.0.12",
+ "@react-email/font": "0.0.6",
+ "@react-email/head": "0.0.9",
+ "@react-email/heading": "0.0.12",
+ "@react-email/hr": "0.0.8",
+ "@react-email/html": "0.0.8",
+ "@react-email/img": "0.0.8",
+ "@react-email/link": "0.0.8",
+ "@react-email/markdown": "0.0.10",
+ "@react-email/preview": "0.0.9",
+ "@react-email/render": "0.0.16",
+ "@react-email/row": "0.0.8",
+ "@react-email/section": "0.0.12",
+ "@react-email/tailwind": "0.0.18",
+ "@react-email/text": "0.0.8"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/container": {
+ "version": "0.0.12",
+ "resolved": "https://registry.npmjs.org/@react-email/container/-/container-0.0.12.tgz",
+ "integrity": "sha512-HFu8Pu5COPFfeZxSL+wKv/TV5uO/sp4zQ0XkRCdnGkj/xoq0lqOHVDL4yC2Pu6fxXF/9C3PHDA++5uEYV5WVJw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/font": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@react-email/font/-/font-0.0.6.tgz",
+ "integrity": "sha512-sZZFvEZ4U3vNCAZ8wXqIO3DuGJR2qE/8m2fEH+tdqwa532zGO3zW+UlCTg0b9455wkJSzEBeaWik0IkNvjXzxw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/head": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/@react-email/head/-/head-0.0.9.tgz",
+ "integrity": "sha512-dF3Uv1qy3oh+IU2atXdv5Xk0hk2udOlMb1A/MNGngC0eHyoEV9ThA0XvhN7mm5x9dDLkVamoWUKXDtmkiuSRqQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/heading": {
+ "version": "0.0.12",
+ "resolved": "https://registry.npmjs.org/@react-email/heading/-/heading-0.0.12.tgz",
+ "integrity": "sha512-eB7mpnAvDmwvQLoPuwEiPRH4fPXWe6ltz6Ptbry2BlI88F0a2k11Ghb4+sZHBqg7vVw/MKbqEgtLqr3QJ/KfCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.0.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/heading/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
+ "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-email/heading/node_modules/@radix-ui/react-slot": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
+ "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.13.10",
+ "@radix-ui/react-compose-refs": "1.0.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-email/hr": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/hr/-/hr-0.0.8.tgz",
+ "integrity": "sha512-JLVvpCg2wYKEB+n/PGCggWG9fRU5e4lxsGdpK5SDLsCL0ic3OLKSpHMfeE+ZSuw0GixAVVQN7F64PVJHQkd4MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/html": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/html/-/html-0.0.8.tgz",
+ "integrity": "sha512-arII3wBNLpeJtwyIJXPaILm5BPKhA+nvdC1F9QkuKcOBJv2zXctn8XzPqyGqDfdplV692ulNJP7XY55YqbKp6w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/img": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/img/-/img-0.0.8.tgz",
+ "integrity": "sha512-jx/rPuKo31tV18fu7P5rRqelaH5wkhg83Dq7uLwJpfqhbi4KFBGeBfD0Y3PiLPPoh+WvYf+Adv9W2ghNW8nOMQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/link": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/link/-/link-0.0.8.tgz",
+ "integrity": "sha512-nVikuTi8WJHa6Baad4VuRUbUCa/7EtZ1Qy73TRejaCHn+vhetc39XGqHzKLNh+Z/JFL8Hv9g+4AgG16o2R0ogQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/markdown": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/@react-email/markdown/-/markdown-0.0.10.tgz",
+ "integrity": "sha512-MH0xO+NJ4IuJcx9nyxbgGKAMXyudFjCZ0A2GQvuWajemW9qy2hgnJ3mW3/z5lwcenG+JPn7JyO/iZpizQ7u1tA==",
+ "license": "MIT",
+ "dependencies": {
+ "md-to-react-email": "5.0.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/preview": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/@react-email/preview/-/preview-0.0.9.tgz",
+ "integrity": "sha512-2fyAA/zzZYfYmxfyn3p2YOIU30klyA6Dq4ytyWq4nfzQWWglt5hNDE0cMhObvRtfjM9ghMSVtoELAb0MWiF/kw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/render": {
+ "version": "0.0.16",
+ "resolved": "https://registry.npmjs.org/@react-email/render/-/render-0.0.16.tgz",
+ "integrity": "sha512-wDaMy27xAq1cJHtSFptp0DTKPuV2GYhloqia95ub/DH9Dea1aWYsbdM918MOc/b/HvVS3w1z8DWzfAk13bGStQ==",
+ "license": "MIT",
+ "dependencies": {
+ "html-to-text": "9.0.5",
+ "js-beautify": "^1.14.11",
+ "react-promise-suspense": "0.3.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/row": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/row/-/row-0.0.8.tgz",
+ "integrity": "sha512-JsB6pxs/ZyjYpEML3nbwJRGAerjcN/Pa/QG48XUwnT/MioDWrUuyQuefw+CwCrSUZ2P1IDrv2tUD3/E3xzcoKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/section": {
+ "version": "0.0.12",
+ "resolved": "https://registry.npmjs.org/@react-email/section/-/section-0.0.12.tgz",
+ "integrity": "sha512-UCD/N/BeOTN4h3VZBUaFdiSem6HnpuxD1Q51TdBFnqeNqS5hBomp8LWJJ9s4gzwHWk1XPdNfLA3I/fJwulJshg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/tailwind": {
+ "version": "0.0.18",
+ "resolved": "https://registry.npmjs.org/@react-email/tailwind/-/tailwind-0.0.18.tgz",
+ "integrity": "sha512-ob8CXX/Pqq1U8YfL5OJTL48WJkixizyoXMMRYTiDLDN9LVLU7lSLtcK9kOD9CgFbO2yUPQr7/5+7gnQJ+cXa8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@react-email/text": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@react-email/text/-/text-0.0.8.tgz",
+ "integrity": "sha512-uvN2TNWMrfC9wv/LLmMLbbEN1GrMWZb9dBK14eYxHHAEHCeyvGb5ePZZ2MPyzO7Y5yTC+vFEnCEr76V+hWMxCQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/@remix-run/dev": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.10.3.tgz",
+ "integrity": "sha512-ZbSslRCPVsXispbu1t/khMrMwJ34R695tGujnya696nAW0v8rocVhEwaUpvR2iwnvGKN372gv4SdJrjnYz45kw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.21.8",
+ "@babel/generator": "^7.21.5",
+ "@babel/parser": "^7.21.8",
+ "@babel/plugin-syntax-decorators": "^7.22.10",
+ "@babel/plugin-syntax-jsx": "^7.21.4",
+ "@babel/preset-typescript": "^7.21.5",
+ "@babel/traverse": "^7.23.2",
+ "@babel/types": "^7.22.5",
+ "@mdx-js/mdx": "^2.3.0",
+ "@npmcli/package-json": "^4.0.1",
+ "@remix-run/node": "2.10.3",
+ "@remix-run/router": "1.18.0",
+ "@remix-run/server-runtime": "2.10.3",
+ "@types/mdx": "^2.0.5",
+ "@vanilla-extract/integration": "^6.2.0",
+ "arg": "^5.0.1",
+ "cacache": "^17.1.3",
+ "chalk": "^4.1.2",
+ "chokidar": "^3.5.1",
+ "cross-spawn": "^7.0.3",
+ "dotenv": "^16.0.0",
+ "es-module-lexer": "^1.3.1",
+ "esbuild": "0.17.6",
+ "esbuild-plugins-node-modules-polyfill": "^1.6.0",
+ "execa": "5.1.1",
+ "exit-hook": "2.2.1",
+ "express": "^4.19.2",
+ "fs-extra": "^10.0.0",
+ "get-port": "^5.1.1",
+ "gunzip-maybe": "^1.4.2",
+ "jsesc": "3.0.2",
+ "json5": "^2.2.2",
+ "lodash": "^4.17.21",
+ "lodash.debounce": "^4.0.8",
+ "minimatch": "^9.0.0",
+ "ora": "^5.4.1",
+ "picocolors": "^1.0.0",
+ "picomatch": "^2.3.1",
+ "pidtree": "^0.6.0",
+ "postcss": "^8.4.19",
+ "postcss-discard-duplicates": "^5.1.0",
+ "postcss-load-config": "^4.0.1",
+ "postcss-modules": "^6.0.0",
+ "prettier": "^2.7.1",
+ "pretty-ms": "^7.0.1",
+ "react-refresh": "^0.14.0",
+ "remark-frontmatter": "4.0.1",
+ "remark-mdx-frontmatter": "^1.0.1",
+ "semver": "^7.3.7",
+ "set-cookie-parser": "^2.6.0",
+ "tar-fs": "^2.1.1",
+ "tsconfig-paths": "^4.0.0",
+ "ws": "^7.4.5"
+ },
+ "bin": {
+ "remix": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@remix-run/react": "^2.10.3",
+ "@remix-run/serve": "^2.10.3",
+ "typescript": "^5.1.0",
+ "vite": "^5.1.0",
+ "wrangler": "^3.28.2"
+ },
+ "peerDependenciesMeta": {
+ "@remix-run/serve": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ },
+ "wrangler": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/android-arm": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.6.tgz",
+ "integrity": "sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/android-arm64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.6.tgz",
+ "integrity": "sha512-YnYSCceN/dUzUr5kdtUzB+wZprCafuD89Hs0Aqv9QSdwhYQybhXTaSTcrl6X/aWThn1a/j0eEpUBGOE7269REg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/android-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.6.tgz",
+ "integrity": "sha512-MVcYcgSO7pfu/x34uX9u2QIZHmXAB7dEiLQC5bBl5Ryqtpj9lT2sg3gNDEsrPEmimSJW2FXIaxqSQ501YLDsZQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.6.tgz",
+ "integrity": "sha512-bsDRvlbKMQMt6Wl08nHtFz++yoZHsyTOxnjfB2Q95gato+Yi4WnRl13oC2/PJJA9yLCoRv9gqT/EYX0/zDsyMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/darwin-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.6.tgz",
+ "integrity": "sha512-xh2A5oPrYRfMFz74QXIQTQo8uA+hYzGWJFoeTE8EvoZGHb+idyV4ATaukaUvnnxJiauhs/fPx3vYhU4wiGfosg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.6.tgz",
+ "integrity": "sha512-EnUwjRc1inT4ccZh4pB3v1cIhohE2S4YXlt1OvI7sw/+pD+dIE4smwekZlEPIwY6PhU6oDWwITrQQm5S2/iZgg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.6.tgz",
+ "integrity": "sha512-Uh3HLWGzH6FwpviUcLMKPCbZUAFzv67Wj5MTwK6jn89b576SR2IbEp+tqUHTr8DIl0iDmBAf51MVaP7pw6PY5Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-arm": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.6.tgz",
+ "integrity": "sha512-7YdGiurNt7lqO0Bf/U9/arrPWPqdPqcV6JCZda4LZgEn+PTQ5SMEI4MGR52Bfn3+d6bNEGcWFzlIxiQdS48YUw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-arm64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.6.tgz",
+ "integrity": "sha512-bUR58IFOMJX523aDVozswnlp5yry7+0cRLCXDsxnUeQYJik1DukMY+apBsLOZJblpH+K7ox7YrKrHmJoWqVR9w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-ia32": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.6.tgz",
+ "integrity": "sha512-ujp8uoQCM9FRcbDfkqECoARsLnLfCUhKARTP56TFPog8ie9JG83D5GVKjQ6yVrEVdMie1djH86fm98eY3quQkQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-loong64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.6.tgz",
+ "integrity": "sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.6.tgz",
+ "integrity": "sha512-09AXKB1HDOzXD+j3FdXCiL/MWmZP0Ex9eR8DLMBVcHorrWJxWmY8Nms2Nm41iRM64WVx7bA/JVHMv081iP2kUA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.6.tgz",
+ "integrity": "sha512-AmLhMzkM8JuqTIOhxnX4ubh0XWJIznEynRnZAVdA2mMKE6FAfwT2TWKTwdqMG+qEaeyDPtfNoZRpJbD4ZBv0Tg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.6.tgz",
+ "integrity": "sha512-Y4Ri62PfavhLQhFbqucysHOmRamlTVK10zPWlqjNbj2XMea+BOs4w6ASKwQwAiqf9ZqcY9Ab7NOU4wIgpxwoSQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-s390x": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.6.tgz",
+ "integrity": "sha512-SPUiz4fDbnNEm3JSdUW8pBJ/vkop3M1YwZAVwvdwlFLoJwKEZ9L98l3tzeyMzq27CyepDQ3Qgoba44StgbiN5Q==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/linux-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.6.tgz",
+ "integrity": "sha512-a3yHLmOodHrzuNgdpB7peFGPx1iJ2x6m+uDvhP2CKdr2CwOaqEFMeSqYAHU7hG+RjCq8r2NFujcd/YsEsFgTGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.6.tgz",
+ "integrity": "sha512-EanJqcU/4uZIBreTrnbnre2DXgXSa+Gjap7ifRfllpmyAU7YMvaXmljdArptTHmjrkkKm9BK6GH5D5Yo+p6y5A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.6.tgz",
+ "integrity": "sha512-xaxeSunhQRsTNGFanoOkkLtnmMn5QbA0qBhNet/XLVsc+OVkpIWPHcr3zTW2gxVU5YOHFbIHR9ODuaUdNza2Vw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/sunos-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.6.tgz",
+ "integrity": "sha512-gnMnMPg5pfMkZvhHee21KbKdc6W3GR8/JuE0Da1kjwpK6oiFU3nqfHuVPgUX2rsOx9N2SadSQTIYV1CIjYG+xw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/win32-arm64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.6.tgz",
+ "integrity": "sha512-G95n7vP1UnGJPsVdKXllAJPtqjMvFYbN20e8RK8LVLhlTiSOH1sd7+Gt7rm70xiG+I5tM58nYgwWrLs6I1jHqg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/win32-ia32": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.6.tgz",
+ "integrity": "sha512-96yEFzLhq5bv9jJo5JhTs1gI+1cKQ83cUpyxHuGqXVwQtY5Eq54ZEsKs8veKtiKwlrNimtckHEkj4mRh4pPjsg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/@esbuild/win32-x64": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.6.tgz",
+ "integrity": "sha512-n6d8MOyUrNp6G4VSpRcgjs5xj4A91svJSaiwLIDWVWEsZtpN5FA9NlBbZHDmAJc2e8e6SF4tkBD3HAvPF+7igA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@remix-run/dev/node_modules/esbuild": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.6.tgz",
+ "integrity": "sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.17.6",
+ "@esbuild/android-arm64": "0.17.6",
+ "@esbuild/android-x64": "0.17.6",
+ "@esbuild/darwin-arm64": "0.17.6",
+ "@esbuild/darwin-x64": "0.17.6",
+ "@esbuild/freebsd-arm64": "0.17.6",
+ "@esbuild/freebsd-x64": "0.17.6",
+ "@esbuild/linux-arm": "0.17.6",
+ "@esbuild/linux-arm64": "0.17.6",
+ "@esbuild/linux-ia32": "0.17.6",
+ "@esbuild/linux-loong64": "0.17.6",
+ "@esbuild/linux-mips64el": "0.17.6",
+ "@esbuild/linux-ppc64": "0.17.6",
+ "@esbuild/linux-riscv64": "0.17.6",
+ "@esbuild/linux-s390x": "0.17.6",
+ "@esbuild/linux-x64": "0.17.6",
+ "@esbuild/netbsd-x64": "0.17.6",
+ "@esbuild/openbsd-x64": "0.17.6",
+ "@esbuild/sunos-x64": "0.17.6",
+ "@esbuild/win32-arm64": "0.17.6",
+ "@esbuild/win32-ia32": "0.17.6",
+ "@esbuild/win32-x64": "0.17.6"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/get-port": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
+ "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/@remix-run/dev/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@remix-run/dev/node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@remix-run/express": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-2.10.3.tgz",
+ "integrity": "sha512-EkSBQAz3ykoGTrCEP2hC1TOn9tQ3zlcWYeJnECinZzzHQ0ERHP6cKlEYV+pOmY1oRDxn8lMxVa+OL+krDA+xbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/node": "2.10.3"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "express": "^4.19.2",
+ "typescript": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/node": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.10.3.tgz",
+ "integrity": "sha512-LBqsgADJKW7tYdJZZi2wu20gfMm6UcOXbvb5U70P2jCNxjJvuIw1gXVvNXRJKAdxPKLonjm8cSpfoI6HeQKEDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/server-runtime": "2.10.3",
+ "@remix-run/web-fetch": "^4.4.2",
+ "@web3-storage/multipart-parser": "^1.0.0",
+ "cookie-signature": "^1.1.0",
+ "source-map-support": "^0.5.21",
+ "stream-slice": "^0.1.2",
+ "undici": "^6.11.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/react": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.10.3.tgz",
+ "integrity": "sha512-nqXlUJzG3zgllsMio20AICbSsF8va0jOnMakl/+oJpFbQqCyFkvYqr+BViBc4Befp5VK54jqJzDnY4kL9zwNvA==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.18.0",
+ "@remix-run/server-runtime": "2.10.3",
+ "react-router": "6.25.0",
+ "react-router-dom": "6.25.0",
+ "turbo-stream": "2.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "typescript": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz",
+ "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@remix-run/server-runtime": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.10.3.tgz",
+ "integrity": "sha512-vUl5jONUI6Lj0ICg9FSRFhoPzQdZ/7dpT1m7ID13DF5BEeF3t/9uCJS61XXWgQ/JEu7YRiwvZiwSRTrgM7zeWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.18.0",
+ "@types/cookie": "^0.6.0",
+ "@web3-storage/multipart-parser": "^1.0.0",
+ "cookie": "^0.6.0",
+ "set-cookie-parser": "^2.4.8",
+ "source-map": "^0.7.3",
+ "turbo-stream": "2.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "typescript": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/testing": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@remix-run/testing/-/testing-2.10.3.tgz",
+ "integrity": "sha512-9Pd6W4fWDbIdkzboYrBlkXGPK8/sZT5qta+QEy0TZZrRZw6FXnYrPgDpjBZAieY4ocRH1zl3Prkm4J9iroNUCg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/node": "2.10.3",
+ "@remix-run/react": "2.10.3",
+ "@remix-run/router": "1.18.0",
+ "react-router-dom": "6.25.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "typescript": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/v1-route-convention": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@remix-run/v1-route-convention/-/v1-route-convention-0.1.4.tgz",
+ "integrity": "sha512-fVTr9YlNLWfaiM/6Y56sOtcY8x1bBJQHY0sDWO5+Z/vjJ2Ni7fe2fwrzs1jUFciMPXqBQdFGePnkuiYLz3cuUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimatch": "^7.4.3"
+ },
+ "peerDependencies": {
+ "@remix-run/dev": "^1.15.0 || ^2.0.0"
+ }
+ },
+ "node_modules/@remix-run/v1-route-convention/node_modules/minimatch": {
+ "version": "7.4.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
+ "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@remix-run/web-blob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.1.0.tgz",
+ "integrity": "sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/web-stream": "^1.1.0",
+ "web-encoding": "1.1.5"
+ }
+ },
+ "node_modules/@remix-run/web-fetch": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.4.2.tgz",
+ "integrity": "sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/web-blob": "^3.1.0",
+ "@remix-run/web-file": "^3.1.0",
+ "@remix-run/web-form-data": "^3.1.0",
+ "@remix-run/web-stream": "^1.1.0",
+ "@web3-storage/multipart-parser": "^1.0.0",
+ "abort-controller": "^3.0.0",
+ "data-uri-to-buffer": "^3.0.1",
+ "mrmime": "^1.0.0"
+ },
+ "engines": {
+ "node": "^10.17 || >=12.3"
+ }
+ },
+ "node_modules/@remix-run/web-file": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/web-file/-/web-file-3.1.0.tgz",
+ "integrity": "sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/web-blob": "^3.1.0"
+ }
+ },
+ "node_modules/@remix-run/web-form-data": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/web-form-data/-/web-form-data-3.1.0.tgz",
+ "integrity": "sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==",
+ "license": "MIT",
+ "dependencies": {
+ "web-encoding": "1.1.5"
+ }
+ },
+ "node_modules/@remix-run/web-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/web-stream/-/web-stream-1.1.0.tgz",
+ "integrity": "sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==",
+ "license": "MIT",
+ "dependencies": {
+ "web-streams-polyfill": "^3.1.1"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz",
+ "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz",
+ "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz",
+ "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz",
+ "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz",
+ "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz",
+ "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz",
+ "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz",
+ "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz",
+ "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz",
+ "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz",
+ "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz",
+ "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz",
+ "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz",
+ "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz",
+ "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz",
+ "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@sec-ant/readable-stream": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
+ "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
+ "license": "MIT"
+ },
+ "node_modules/@selderee/plugin-htmlparser2": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
+ "integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "selderee": "^0.11.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
+ "node_modules/@sentry-internal/browser-utils": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.18.0.tgz",
+ "integrity": "sha512-1R7QXp7Gu6ovJGWvGjbgHcDcvDstsQba3miHtUCyDSH9kXtnAVLCAItDkseetFh+JLsjBXf3QFi2H3HPY4hRCw==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry-internal/feedback": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.18.0.tgz",
+ "integrity": "sha512-on6+4ZRkfdnsNgXecGQ6ME8aO26VTzkuM6y/kNN+bG2hSdxsmuU957B4x1Z5wEXiOWswuf3rhqGepg8JIdPkMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry-internal/replay": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.18.0.tgz",
+ "integrity": "sha512-cCLib/HjD8UR0fB2F5hV6KsFBD6yTOEsi67RBllm5gT5vJt87VYoPliF6O7mmMNw8TWkQ0uc5laKld3q9ph+ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry-internal/browser-utils": "8.18.0",
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry-internal/replay-canvas": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.18.0.tgz",
+ "integrity": "sha512-fcuLJBrhw3Ql8sU8veUgDCRYo6toQldFU807cpYphQ0uEw2oVZwNNPDQSu1651Ykvp0P/x+9hk/jjJxMohrO9g==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry-internal/replay": "8.18.0",
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry/babel-plugin-component-annotate": {
+ "version": "2.21.1",
+ "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.21.1.tgz",
+ "integrity": "sha512-u1L8gZ4He0WdyiIsohYkA/YOY1b6Oa5yIMRtfZZ9U5TiWYLgOfMWyb88X0GotZeghSbgxrse/yI4WeHnhAUQDQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@sentry/browser": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.18.0.tgz",
+ "integrity": "sha512-E2w9u76JcjxcmgvroJrB7bcbG5oBCYI/pME1CtprBgZSS9mMYDsyBe6JKqGHdw2wvT3xNxNtkm7hf1O6+3NWUQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry-internal/browser-utils": "8.18.0",
+ "@sentry-internal/feedback": "8.18.0",
+ "@sentry-internal/replay": "8.18.0",
+ "@sentry-internal/replay-canvas": "8.18.0",
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry/bundler-plugin-core": {
+ "version": "2.21.1",
+ "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.21.1.tgz",
+ "integrity": "sha512-F8FdL/bS8cy1SY1Gw0Mfo3ROTqlrq9Lvt5QGvhXi22dpVcDkWmoTWE2k+sMEnXOa8SdThMc/gyC8lMwHGd3kFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.18.5",
+ "@sentry/babel-plugin-component-annotate": "2.21.1",
+ "@sentry/cli": "^2.22.3",
+ "dotenv": "^16.3.1",
+ "find-up": "^5.0.0",
+ "glob": "^9.3.2",
+ "magic-string": "0.30.8",
+ "unplugin": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@sentry/bundler-plugin-core/node_modules/glob": {
+ "version": "9.3.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz",
+ "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "minimatch": "^8.0.2",
+ "minipass": "^4.2.4",
+ "path-scurry": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@sentry/bundler-plugin-core/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz",
+ "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
+ "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@sentry/bundler-plugin-core/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@sentry/bundler-plugin-core/node_modules/path-scurry/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@sentry/cli": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.32.1.tgz",
+ "integrity": "sha512-MWkbkzZfnlE7s2pPbg4VozRSAeMlIObfZlTIou9ye6XnPt6ZmmxCLOuOgSKMv4sXg6aeqKNzMNiadThxCWyvPg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "https-proxy-agent": "^5.0.0",
+ "node-fetch": "^2.6.7",
+ "progress": "^2.0.3",
+ "proxy-from-env": "^1.1.0",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "sentry-cli": "bin/sentry-cli"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@sentry/cli-darwin": "2.32.1",
+ "@sentry/cli-linux-arm": "2.32.1",
+ "@sentry/cli-linux-arm64": "2.32.1",
+ "@sentry/cli-linux-i686": "2.32.1",
+ "@sentry/cli-linux-x64": "2.32.1",
+ "@sentry/cli-win32-i686": "2.32.1",
+ "@sentry/cli-win32-x64": "2.32.1"
+ }
+ },
+ "node_modules/@sentry/cli-darwin": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.32.1.tgz",
+ "integrity": "sha512-z/lEwANTYPCzbWTZ2+eeeNYxRLllC8knd0h+vtAKlhmGw/fyc/N39cznIFyFu+dLJ6tTdjOWOeikHtKuS/7onw==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-arm": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.32.1.tgz",
+ "integrity": "sha512-m0lHkn+o4YKBq8KptGZvpT64FAwSl9mYvHZO9/ChnEGIJ/WyJwiN1X1r9JHVaW4iT5lD0Y5FAyq3JLkk0m0XHg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-arm64": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.32.1.tgz",
+ "integrity": "sha512-hsGqHYuecUl1Yhq4MhiRejfh1gNlmhyNPcQEoO/DDRBnGnJyEAdiDpKXJcc2e/lT9k40B55Ob2CP1SeY040T2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-i686": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.32.1.tgz",
+ "integrity": "sha512-SuMLN1/ceFd3Q/B0DVyh5igjetTAF423txiABAHASenEev0lG0vZkRDXFclfgDtDUKRPmOXW7VDMirM3yZWQHQ==",
+ "cpu": [
+ "x86",
+ "ia32"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-x64": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.32.1.tgz",
+ "integrity": "sha512-x4FGd6xgvFddz8V/dh6jii4wy9qjWyvYLBTz8Fhi9rIP+b8wQ3oxwHIdzntareetZP7C1ggx+hZheiYocNYVwA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-i686": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.32.1.tgz",
+ "integrity": "sha512-i6aZma9mFzR+hqMY5VliQZEX6ypP/zUjPK0VtIMYWs5cC6PsQLRmuoeJmy3Z7d4nlh0CdK5NPC813Ej6RY6/vg==",
+ "cpu": [
+ "x86",
+ "ia32"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-x64": {
+ "version": "2.32.1",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.32.1.tgz",
+ "integrity": "sha512-B58w/lRHLb4MUSjJNfMMw2cQykfimDCMLMmeK+1EiT2RmSeNQliwhhBxYcKk82a8kszH6zg3wT2vCea7LyPUyA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@sentry/core": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.18.0.tgz",
+ "integrity": "sha512-8moEMC3gp4W6mH9w5amb/zrYk6bNW8WGgcLRMCs5rguxny8YP5i8ISOJ0T0LP9x/RxSK/6xix5D2bzI/5ECzlw==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry/node": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.18.0.tgz",
+ "integrity": "sha512-a+W477bmt28I1DT51xJKmp4Y7hBAdEGqQ2K7gfOn3mRBHoihuhKl2Xe8BMwFH7+v4mAEZEwAZBUOLAC7h+Tjig==",
+ "license": "MIT",
+ "dependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/context-async-hooks": "^1.25.1",
+ "@opentelemetry/core": "^1.25.1",
+ "@opentelemetry/instrumentation": "^0.52.1",
+ "@opentelemetry/instrumentation-connect": "0.38.0",
+ "@opentelemetry/instrumentation-express": "0.41.0",
+ "@opentelemetry/instrumentation-fastify": "0.38.0",
+ "@opentelemetry/instrumentation-graphql": "0.42.0",
+ "@opentelemetry/instrumentation-hapi": "0.40.0",
+ "@opentelemetry/instrumentation-http": "0.52.1",
+ "@opentelemetry/instrumentation-ioredis": "0.42.0",
+ "@opentelemetry/instrumentation-koa": "0.42.0",
+ "@opentelemetry/instrumentation-mongodb": "0.46.0",
+ "@opentelemetry/instrumentation-mongoose": "0.40.0",
+ "@opentelemetry/instrumentation-mysql": "0.40.0",
+ "@opentelemetry/instrumentation-mysql2": "0.40.0",
+ "@opentelemetry/instrumentation-nestjs-core": "0.39.0",
+ "@opentelemetry/instrumentation-pg": "0.43.0",
+ "@opentelemetry/instrumentation-redis-4": "0.41.0",
+ "@opentelemetry/resources": "^1.25.1",
+ "@opentelemetry/sdk-trace-base": "^1.25.1",
+ "@opentelemetry/semantic-conventions": "^1.25.1",
+ "@prisma/instrumentation": "5.16.1",
+ "@sentry/core": "8.18.0",
+ "@sentry/opentelemetry": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ },
+ "optionalDependencies": {
+ "opentelemetry-instrumentation-fetch-node": "1.2.3"
+ }
+ },
+ "node_modules/@sentry/opentelemetry": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.18.0.tgz",
+ "integrity": "sha512-P2OoXXJcU2RiRZmpBqOkK+NLGkwQrYizlOHl1zckHI1nYmQgOD1tcJj4c1xOYzH+eGPLp/IViXHO6vaBr8BGGg==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "@opentelemetry/core": "^1.25.1",
+ "@opentelemetry/instrumentation": "^0.52.1",
+ "@opentelemetry/sdk-trace-base": "^1.25.1",
+ "@opentelemetry/semantic-conventions": "^1.25.1"
+ }
+ },
+ "node_modules/@sentry/profiling-node": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/profiling-node/-/profiling-node-8.18.0.tgz",
+ "integrity": "sha512-bgX8aPRQe8o+KDS4CgWCayCRs3BC6t6oqto1vU1h7/Nzg2XuI8xPFlaalZ/ihFvpWO+qBJZvlMu4Z9zDBWeFfQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/core": "8.18.0",
+ "@sentry/node": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0",
+ "detect-libc": "^2.0.2",
+ "node-abi": "^3.61.0"
+ },
+ "bin": {
+ "sentry-prune-profiler-binaries": "scripts/prune-profiler-binaries.js"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry/react": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.18.0.tgz",
+ "integrity": "sha512-ckCKdxmeFdfR6moE/Aiq+cJyQuCUKoUqU/++xZwqVbgecuImsk4s7CzzpX9T6JoYK7jqru2SvuRSiwcdtLN6AQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/browser": "8.18.0",
+ "@sentry/core": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0",
+ "hoist-non-react-statics": "^3.3.2"
+ },
+ "engines": {
+ "node": ">=14.18"
+ },
+ "peerDependencies": {
+ "react": "^16.14.0 || 17.x || 18.x || 19.x"
+ }
+ },
+ "node_modules/@sentry/remix": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/remix/-/remix-8.18.0.tgz",
+ "integrity": "sha512-jrKDZnLS++sTa9YjkmE1ii2akgt9fRYvfWLcMMBOiMZvelErXSBsyOMDPvH0QYlKDw8ioIvlEf7WI4GB+R9gWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@opentelemetry/instrumentation-http": "0.52.1",
+ "@remix-run/router": "1.x",
+ "@sentry/cli": "^2.32.1",
+ "@sentry/core": "8.18.0",
+ "@sentry/node": "8.18.0",
+ "@sentry/opentelemetry": "8.18.0",
+ "@sentry/react": "8.18.0",
+ "@sentry/types": "8.18.0",
+ "@sentry/utils": "8.18.0",
+ "glob": "^10.3.4",
+ "opentelemetry-instrumentation-remix": "0.7.1",
+ "yargs": "^17.6.0"
+ },
+ "bin": {
+ "sentry-upload-sourcemaps": "scripts/sentry-upload-sourcemaps.js"
+ },
+ "engines": {
+ "node": ">=14.18"
+ },
+ "peerDependencies": {
+ "@remix-run/node": "1.x || 2.x",
+ "@remix-run/react": "1.x || 2.x",
+ "react": "16.x || 17.x || 18.x"
+ }
+ },
+ "node_modules/@sentry/remix/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@sentry/remix/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/@sentry/remix/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@sentry/remix/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@sentry/types": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.18.0.tgz",
+ "integrity": "sha512-5J+uOqptnmAnW3Rk31AHIqW36Wzvlo3UOM+p2wjSYGrC/PgcE47Klzr+w4UcOhN6AZqefalGd3vaUXz9NaFdRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry/utils": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.18.0.tgz",
+ "integrity": "sha512-7wq7cgaeSIGJncl9/2VMu81ZN5ep4lp4H1/+O8+xUxOmnPb/05ZZcbn9/VxVQvIoqZSZdwCLPeBz6PEVukvokA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/types": "8.18.0"
+ },
+ "engines": {
+ "node": ">=14.18"
+ }
+ },
+ "node_modules/@sentry/vite-plugin": {
+ "version": "2.21.1",
+ "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-2.21.1.tgz",
+ "integrity": "sha512-i2PqeLafGBcSROnmr9mS0dL2/JBJji/4rJZ2U2A+tqtAhDAAaCUNalbn6xLp/hawLExt/wRuBj1J7j46sGDOaA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/bundler-plugin-core": "2.21.1",
+ "unplugin": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@sindresorhus/merge-streams": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
+ "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/@sly-cli/sly/-/sly-1.13.0.tgz",
+ "integrity": "sha512-h1CWj26bTnWtZRwsLWDmFEA/3slpTnons1l73cAlkLeDoq6e/l8fGY9J4V22en9noG4vWsNjB38Ej9VR+fZCyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@epic-web/cachified": "^5.1.2",
+ "chalk": "^5.3.0",
+ "commander": "^11.0.0",
+ "compare-versions": "^6.0.0",
+ "cosmiconfig": "^8.2.0",
+ "esbuild": "^0.19.11",
+ "execa": "^7.1.1",
+ "lru-cache": "^10.0.0",
+ "ora": "^6.3.1",
+ "prompts": "^2.4.2",
+ "zod": "^3.21.4"
+ },
+ "bin": {
+ "sly": "start.js"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
+ "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/android-arm": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
+ "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/android-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
+ "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/android-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
+ "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
+ "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/darwin-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
+ "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
+ "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
+ "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-arm": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
+ "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
+ "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-ia32": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
+ "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-loong64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
+ "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
+ "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
+ "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
+ "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-s390x": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
+ "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/linux-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
+ "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
+ "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
+ "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/sunos-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
+ "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/win32-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
+ "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/win32-ia32": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
+ "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/@esbuild/win32-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
+ "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/cli-cursor": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
+ "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/esbuild": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
+ "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=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"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/execa": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz",
+ "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/is-interactive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
+ "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/is-unicode-supported": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+ "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/log-symbols": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
+ "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.0.0",
+ "is-unicode-supported": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@sly-cli/sly/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/ora": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.1.tgz",
+ "integrity": "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.0.0",
+ "cli-cursor": "^4.0.0",
+ "cli-spinners": "^2.6.1",
+ "is-interactive": "^2.0.0",
+ "is-unicode-supported": "^1.1.0",
+ "log-symbols": "^5.1.0",
+ "stdin-discarder": "^0.1.0",
+ "strip-ansi": "^7.0.1",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/restore-cursor": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
+ "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/restore-cursor/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/restore-cursor/node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@sly-cli/sly/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@sly-cli/sly/node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@testing-library/dom": {
+ "version": "10.3.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.2.tgz",
+ "integrity": "sha512-0bxIdP9mmPiOJ6wHLj8bdJRq+51oddObeCGdEf6PNEhYd93ZYAN+lPRnEOVFtheVwDM7+p+tza3LAQgp0PTudg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@testing-library/dom/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@testing-library/dom/node_modules/dom-accessibility-api": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
+ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@testing-library/jest-dom": {
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.6.tgz",
+ "integrity": "sha512-8qpnGVincVDLEcQXWaHOf6zmlbwTKc6Us6PPu4CRnPXCzo2OGBS5cwgMMOWdxDpEz1mkbvXHpEy99M5Yvt682w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@adobe/css-tools": "^4.4.0",
+ "@babel/runtime": "^7.9.2",
+ "aria-query": "^5.0.0",
+ "chalk": "^3.0.0",
+ "css.escape": "^1.5.1",
+ "dom-accessibility-api": "^0.6.3",
+ "lodash": "^4.17.21",
+ "redent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ },
+ "peerDependencies": {
+ "@jest/globals": ">= 28",
+ "@types/bun": "latest",
+ "@types/jest": ">= 28",
+ "jest": ">= 28",
+ "vitest": ">= 0.32"
+ },
+ "peerDependenciesMeta": {
+ "@jest/globals": {
+ "optional": true
+ },
+ "@types/bun": {
+ "optional": true
+ },
+ "@types/jest": {
+ "optional": true
+ },
+ "jest": {
+ "optional": true
+ },
+ "vitest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@testing-library/react": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz",
+ "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": "^10.0.0",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@testing-library/user-event": {
+ "version": "14.5.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz",
+ "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": ">=7.21.4"
+ }
+ },
+ "node_modules/@total-typescript/ts-reset": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@total-typescript/ts-reset/-/ts-reset-0.5.1.tgz",
+ "integrity": "sha512-AqlrT8YA1o7Ff5wPfMOL0pvL+1X+sw60NN6CcOCqs658emD6RfiXhF7Gu9QcfKBH7ELY2nInLhKSCWVoNL70MQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/acorn": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz",
+ "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/aria-query": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
+ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/bcryptjs": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
+ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/better-sqlite3": {
+ "version": "7.6.11",
+ "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.11.tgz",
+ "integrity": "sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.5",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
+ "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/compression": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz",
+ "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.36",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz",
+ "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/debug": {
+ "version": "4.1.12",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+ "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*"
+ }
+ },
+ "node_modules/@types/eslint": {
+ "version": "8.56.10",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
+ "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
+ "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.2.tgz",
+ "integrity": "sha512-dPSEQElyVJ97BuGduAqQjpBocZWAs0GR94z+ptL7JXQJeJdHw2WBG3EWdFrK36b8Q6j8P4cXOMhgUoi0IIfIsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/fs-extra": {
+ "version": "11.0.4",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz",
+ "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/jsonfile": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/hast": {
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz",
+ "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
+ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/jsonfile": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz",
+ "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "3.0.15",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
+ "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2"
+ }
+ },
+ "node_modules/@types/mdx": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz",
+ "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/morgan": {
+ "version": "1.9.9",
+ "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz",
+ "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/ms": {
+ "version": "0.7.34",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz",
+ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/mute-stream": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz",
+ "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mysql": {
+ "version": "2.15.22",
+ "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.22.tgz",
+ "integrity": "sha512-wK1pzsJVVAjYCSZWQoWHziQZbNggXFDUEIGf54g4ZM/ERuP86uGdWeKZWMYlqTPMZfHJJvLPyogXGvCOg87yLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "20.14.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz",
+ "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/@types/pg": {
+ "version": "8.6.1",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz",
+ "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^2.2.0"
+ }
+ },
+ "node_modules/@types/pg-pool": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.4.tgz",
+ "integrity": "sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/pg": "*"
+ }
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.12",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
+ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/qrcode": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
+ "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.15",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz",
+ "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.3",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
+ "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
+ "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.8",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+ "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
+ "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.7",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
+ "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/set-cookie-parser": {
+ "version": "2.4.10",
+ "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.10.tgz",
+ "integrity": "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/shimmer": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz",
+ "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/source-map-support": {
+ "version": "0.5.10",
+ "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.10.tgz",
+ "integrity": "sha512-tgVP2H469x9zq34Z0m/fgPewGhg/MLClalNOiPIzQlXrSS2YrKu/xCdSCKnEDwkFha51VKEKB6A9wW26/ZNwzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/@types/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@types/statuses": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz",
+ "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/unist": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
+ "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/wrap-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz",
+ "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-/dBqhcdiVHB3SzaU5Mczy1QoVel8hZ8TX7T2WE1Qq2ujrv4X9I2/H2DMHnNtmlcGY9hcezsPtu76BTiZAeMQqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.0.0-alpha.20",
+ "@typescript-eslint/type-utils": "8.0.0-alpha.20",
+ "@typescript-eslint/utils": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-+Ncj0Q6DT8ZHYNp8h5RndW4Siv52kiPpHEz/i8Sj2rh2y8ZCc5pKSHSslk+eZi0Bdj+/+swNOmDNcL2CrlaEnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-xpU1rMQfnnNZxpHN6YUfr18sGOMcpC9hvt54fupcU6N1qMCagEtkRt1U15x086oJAgAITJGa67454ffAoCxv/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-VQ8Mf8upDCuf0uMTjX/Pdw3gvCZomkG43nuThUuzhK3YFwFmIDTqx0ZWSsYJkVGfll0WrXgIua+rKSP/n6NBWw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-0aMhjDTvIrkGkHqyM0ZByAwR8BV1f2HhKdYyjtxko8S/Ca4PGjOIjub6VoF+bQwCRxEuV8viNUld78rqm9jqLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.0.0-alpha.20",
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/typescript-estree": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-ej06rfct0kalfJgIR8nTR7dF1mgfF83hkylrYas7IAElHfgw4zx99BUGa6VrnHZ1PkxdJBp5PgcO2FmmlOoaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-C1gnMM1k6i0phZ7l6HJPecVIGMErrONnurQ9ssRBZNek7gJInDGEDUC7LlL3QIWxFkHcdwYXWzuc7IueyxU6YQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.0.0-alpha.20",
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/typescript-estree": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-+Ncj0Q6DT8ZHYNp8h5RndW4Siv52kiPpHEz/i8Sj2rh2y8ZCc5pKSHSslk+eZi0Bdj+/+swNOmDNcL2CrlaEnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-xpU1rMQfnnNZxpHN6YUfr18sGOMcpC9hvt54fupcU6N1qMCagEtkRt1U15x086oJAgAITJGa67454ffAoCxv/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-VQ8Mf8upDCuf0uMTjX/Pdw3gvCZomkG43nuThUuzhK3YFwFmIDTqx0ZWSsYJkVGfll0WrXgIua+rKSP/n6NBWw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-ej06rfct0kalfJgIR8nTR7dF1mgfF83hkylrYas7IAElHfgw4zx99BUGa6VrnHZ1PkxdJBp5PgcO2FmmlOoaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz",
+ "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/visitor-keys": "7.11.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-/eUDosUnJlEwzRFPwaKYM3H0VS+40oXx+5ZN+CFCtdXMZjGsTwKM3XNvI+4orisjn+qhNVlHZby4PHnH8qAh8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "8.0.0-alpha.20",
+ "@typescript-eslint/utils": "8.0.0-alpha.20",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-+Ncj0Q6DT8ZHYNp8h5RndW4Siv52kiPpHEz/i8Sj2rh2y8ZCc5pKSHSslk+eZi0Bdj+/+swNOmDNcL2CrlaEnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-xpU1rMQfnnNZxpHN6YUfr18sGOMcpC9hvt54fupcU6N1qMCagEtkRt1U15x086oJAgAITJGa67454ffAoCxv/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-VQ8Mf8upDCuf0uMTjX/Pdw3gvCZomkG43nuThUuzhK3YFwFmIDTqx0ZWSsYJkVGfll0WrXgIua+rKSP/n6NBWw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-0aMhjDTvIrkGkHqyM0ZByAwR8BV1f2HhKdYyjtxko8S/Ca4PGjOIjub6VoF+bQwCRxEuV8viNUld78rqm9jqLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.0.0-alpha.20",
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/typescript-estree": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-ej06rfct0kalfJgIR8nTR7dF1mgfF83hkylrYas7IAElHfgw4zx99BUGa6VrnHZ1PkxdJBp5PgcO2FmmlOoaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz",
+ "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz",
+ "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/visitor-keys": "7.11.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz",
+ "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "7.11.0",
+ "@typescript-eslint/types": "7.11.0",
+ "@typescript-eslint/typescript-estree": "7.11.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.11.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz",
+ "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "7.11.0",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@vanilla-extract/babel-plugin-debug-ids": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@vanilla-extract/babel-plugin-debug-ids/-/babel-plugin-debug-ids-1.0.6.tgz",
+ "integrity": "sha512-C188vUEYmw41yxg3QooTs8r1IdbDQQ2mH7L5RkORBnHx74QlmsNfqVmKwAVTgrlYt8JoRaWMtPfGm/Ql0BNQrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.23.9"
+ }
+ },
+ "node_modules/@vanilla-extract/css": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/@vanilla-extract/css/-/css-1.15.2.tgz",
+ "integrity": "sha512-Bi61iCAtojCuqvV+FYaF5i69vBjuMQJpHPdpgKYyQvx+e2Hp79V0ELglyYOdcyg9Wh0k0MFwgCDipVd7EloTXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@emotion/hash": "^0.9.0",
+ "@vanilla-extract/private": "^1.0.5",
+ "css-what": "^6.1.0",
+ "cssesc": "^3.0.0",
+ "csstype": "^3.0.7",
+ "dedent": "^1.5.3",
+ "deep-object-diff": "^1.1.9",
+ "deepmerge": "^4.2.2",
+ "media-query-parser": "^2.0.2",
+ "modern-ahocorasick": "^1.0.0",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "node_modules/@vanilla-extract/integration": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/@vanilla-extract/integration/-/integration-6.5.0.tgz",
+ "integrity": "sha512-E2YcfO8vA+vs+ua+gpvy1HRqvgWbI+MTlUpxA8FvatOvybuNcWAY0CKwQ/Gpj7rswYKtC6C7+xw33emM6/ImdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.20.7",
+ "@babel/plugin-syntax-typescript": "^7.20.0",
+ "@vanilla-extract/babel-plugin-debug-ids": "^1.0.4",
+ "@vanilla-extract/css": "^1.14.0",
+ "esbuild": "npm:esbuild@~0.17.6 || ~0.18.0 || ~0.19.0",
+ "eval": "0.1.8",
+ "find-up": "^5.0.0",
+ "javascript-stringify": "^2.0.1",
+ "lodash": "^4.17.21",
+ "mlly": "^1.4.2",
+ "outdent": "^0.8.0",
+ "vite": "^5.0.11",
+ "vite-node": "^1.2.0"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
+ "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/android-arm": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
+ "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/android-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
+ "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/android-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
+ "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
+ "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/darwin-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
+ "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
+ "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
+ "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-arm": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
+ "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
+ "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-ia32": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
+ "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-loong64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
+ "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
+ "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
+ "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
+ "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-s390x": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
+ "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/linux-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
+ "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
+ "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
+ "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/sunos-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
+ "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/win32-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
+ "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/win32-ia32": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
+ "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/@esbuild/win32-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
+ "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@vanilla-extract/integration/node_modules/esbuild": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
+ "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=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"
+ }
+ },
+ "node_modules/@vanilla-extract/private": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@vanilla-extract/private/-/private-1.0.5.tgz",
+ "integrity": "sha512-6YXeOEKYTA3UV+RC8DeAjFk+/okoNz/h88R+McnzA2zpaVqTR/Ep+vszkWYlGBcMNO7vEkqbq5nT/JMMvhi+tw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz",
+ "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.5",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.5",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.1",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.14.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0"
+ }
+ },
+ "node_modules/@vitest/coverage-v8": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.0.3.tgz",
+ "integrity": "sha512-53d+6jXFdYbasXBmsL6qaGIfcY5eBQq0sP57AjdasOcSiGNj4qxkkpDKIitUNfjxcfAfUfQ8BD0OR2fSey64+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "@bcoe/v8-coverage": "^0.2.3",
+ "debug": "^4.3.5",
+ "istanbul-lib-coverage": "^3.2.2",
+ "istanbul-lib-report": "^3.0.1",
+ "istanbul-lib-source-maps": "^5.0.6",
+ "istanbul-reports": "^3.1.7",
+ "magic-string": "^0.30.10",
+ "magicast": "^0.3.4",
+ "std-env": "^3.7.0",
+ "strip-literal": "^2.1.0",
+ "test-exclude": "^7.0.1",
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "vitest": "2.0.3"
+ }
+ },
+ "node_modules/@vitest/coverage-v8/node_modules/magic-string": {
+ "version": "0.30.10",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
+ "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.3.tgz",
+ "integrity": "sha512-X6AepoOYePM0lDNUPsGXTxgXZAl3EXd0GYe/MZyVE4HzkUqyUVC6S3PrY5mClDJ6/7/7vALLMV3+xD/Ko60Hqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "2.0.3",
+ "@vitest/utils": "2.0.3",
+ "chai": "^5.1.1",
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.3.tgz",
+ "integrity": "sha512-URM4GLsB2xD37nnTyvf6kfObFafxmycCL8un3OC9gaCs5cti2u+5rJdIflZ2fUJUen4NbvF6jCufwViAFLvz1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.3.tgz",
+ "integrity": "sha512-EmSP4mcjYhAcuBWwqgpjR3FYVeiA4ROzRunqKltWjBfLNs1tnMLtF+qtgd5ClTwkDP6/DGlKJTNa6WxNK0bNYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "2.0.3",
+ "pathe": "^1.1.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.3.tgz",
+ "integrity": "sha512-6OyA6v65Oe3tTzoSuRPcU6kh9m+mPL1vQ2jDlPdn9IQoUxl8rXhBnfICNOC+vwxWY684Vt5UPgtcA2aPFBb6wg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "2.0.3",
+ "magic-string": "^0.30.10",
+ "pathe": "^1.1.2"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot/node_modules/magic-string": {
+ "version": "0.30.10",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
+ "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.3.tgz",
+ "integrity": "sha512-sfqyAw/ypOXlaj4S+w8689qKM1OyPOqnonqOc9T91DsoHbfN5mU7FdifWWv3MtQFf0lEUstEwR9L/q/M390C+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^3.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.3.tgz",
+ "integrity": "sha512-c/UdELMuHitQbbc/EVctlBaxoYAwQPQdSNwv7z/vHyBKy2edYZaFgptE27BRueZB7eW8po+cllotMNTDpL3HWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "2.0.3",
+ "estree-walker": "^3.0.3",
+ "loupe": "^3.1.1",
+ "tinyrainbow": "^1.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@web3-storage/multipart-parser": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz",
+ "integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==",
+ "license": "(Apache-2.0 AND MIT)"
+ },
+ "node_modules/@zeit/schemas": {
+ "version": "2.36.0",
+ "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz",
+ "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@zxing/text-encoding": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
+ "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
+ "license": "(Unlicense OR Apache-2.0)",
+ "optional": true
+ },
+ "node_modules/abbrev": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
+ "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
+ "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-assertions": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
+ "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/acorn-import-attributes": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
+ "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/address": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/address/-/address-2.0.3.tgz",
+ "integrity": "sha512-XNAb/a6TCqou+TufU8/u11HCu9x1gYvOoxLwtlXgIqmkrYQADVv6ljyW2zwiPhHz9R1gItAWpuDrdJMmrOBFEA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16.0.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-align/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ansi-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "license": "MIT"
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arch": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
+ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-hidden": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz",
+ "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
+ "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.toreversed": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz",
+ "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz",
+ "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.1.0",
+ "es-shim-unscopables": "^1.0.2"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+ "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.2.1",
+ "get-intrinsic": "^1.2.3",
+ "is-array-buffer": "^3.0.4",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/astring": {
+ "version": "1.8.6",
+ "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz",
+ "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "astring": "bin/astring"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.19",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz",
+ "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.23.0",
+ "caniuse-lite": "^1.0.30001599",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/babel-dead-code-elimination": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/babel-dead-code-elimination/-/babel-dead-code-elimination-1.0.6.tgz",
+ "integrity": "sha512-JxFi9qyRJpN0LjEbbjbN8g0ux71Qppn9R8Qe3k6QzHg2CaKsbUQtbn307LQGiDLGjV6JCtEFqfxzVig9MyDCHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.23.7",
+ "@babel/parser": "^7.23.6",
+ "@babel/traverse": "^7.23.7",
+ "@babel/types": "^7.23.6"
+ }
+ },
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
+ "license": "MIT"
+ },
+ "node_modules/better-sqlite3": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz",
+ "integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "prebuild-install": "^7.1.1"
+ }
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.52",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
+ "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
+ "dev": true,
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "license": "MIT",
+ "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.11.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/boxen": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz",
+ "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-align": "^3.0.1",
+ "camelcase": "^7.0.0",
+ "chalk": "^5.0.1",
+ "cli-boxes": "^3.0.0",
+ "string-width": "^5.1.2",
+ "type-fest": "^2.13.0",
+ "widest-line": "^4.0.1",
+ "wrap-ansi": "^8.0.1"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/camelcase": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz",
+ "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserify-zlib": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+ "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pako": "~0.2.0"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.23.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
+ "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001587",
+ "electron-to-chromium": "^1.4.668",
+ "node-releases": "^2.0.14",
+ "update-browserslist-db": "^1.0.13"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "license": "MIT"
+ },
+ "node_modules/bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/cac": {
+ "version": "6.7.14",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cacache": {
+ "version": "17.1.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz",
+ "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@npmcli/fs": "^3.1.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^7.7.1",
+ "minipass": "^7.0.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "p-map": "^4.0.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/cacache/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cacache/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "license": "MIT",
+ "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.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001625",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001625.tgz",
+ "integrity": "sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chai": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz",
+ "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz",
+ "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk-template?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk-template/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/chalk-template/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/character-entities": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+ "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
+ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz",
+ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==",
+ "license": "MIT"
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz",
+ "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "2.0.0"
+ },
+ "funding": {
+ "url": "https://joebell.co.uk"
+ }
+ },
+ "node_modules/class-variance-authority/node_modules/clsx": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
+ "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
+ "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/clipboardy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz",
+ "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "arch": "^2.2.0",
+ "execa": "^5.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/clipboardy/node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/clipboardy/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/clipboardy/node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/clipboardy/node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/clipboardy/node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/clipboardy/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/clipboardy/node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/cliui/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/cliui/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/close-with-grace": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/close-with-grace/-/close-with-grace-1.3.0.tgz",
+ "integrity": "sha512-lvm0rmLIR5bNz4CRKW6YvCfn9Wg5Wb9A8PJ3Bb+hjyikgC1RO1W3J4z9rBXQYw97mAte7dNSQI8BmUsxdlXQyw==",
+ "license": "MIT"
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/compare-versions": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz",
+ "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/compression/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/compression/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/confbox": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz",
+ "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-disposition/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.1.tgz",
+ "integrity": "sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cosmiconfig": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+ "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0",
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cross-env": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
+ "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.1"
+ },
+ "bin": {
+ "cross-env": "src/bin/cross-env.js",
+ "cross-env-shell": "src/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=10.14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cross-spawn/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypto-js": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
+ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
+ "license": "MIT"
+ },
+ "node_modules/css-select": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+ "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css.escape": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
+ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cssstyle": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz",
+ "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "rrweb-cssom": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cssstyle/node_modules/rrweb-cssom": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz",
+ "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz",
+ "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/data-urls": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
+ "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
+ "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
+ "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/date-fns": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
+ "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/decode-named-character-reference": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
+ "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "character-entities": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deep-object-diff": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz",
+ "integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dijkstrajs": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
+ "license": "MIT"
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/discontinuous-range": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+ "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "license": "MIT"
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-accessibility-api": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz",
+ "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "node_modules/duplexify/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/duplexify/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/duplexify/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
+ },
+ "node_modules/editorconfig": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
+ "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@one-ini/wasm": "0.1.1",
+ "commander": "^10.0.0",
+ "minimatch": "9.0.1",
+ "semver": "^7.5.3"
+ },
+ "bin": {
+ "editorconfig": "bin/editorconfig"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/minimatch": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
+ "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.784",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.784.tgz",
+ "integrity": "sha512-9CZwh+sDrhDAeOEFh8s3PqwduzTyYIeYwZolc1b9ENAUt3ePu7R1sJSCWr/820ISssRxCJUyHI9Wb7j+0Uo1AA==",
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/encode-utf8": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
+ "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/enforce-unique": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/enforce-unique/-/enforce-unique-1.3.0.tgz",
+ "integrity": "sha512-VaNJOwgNeOtZ4qvfGO5OsRWnbvF3jX0/v/3I2YSFpOnPwWj/spbDz1Ktbi5Z9v/eGgcqCqeghW1wkCnSWF4jcg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.23.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
+ "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "arraybuffer.prototype.slice": "^1.0.3",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "data-view-buffer": "^1.0.1",
+ "data-view-byte-length": "^1.0.1",
+ "data-view-byte-offset": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-set-tostringtag": "^2.0.3",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.6",
+ "get-intrinsic": "^1.2.4",
+ "get-symbol-description": "^1.0.2",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.3",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.0.7",
+ "is-array-buffer": "^3.0.4",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.1",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.3",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.13",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.13.1",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.5",
+ "regexp.prototype.flags": "^1.5.2",
+ "safe-array-concat": "^1.1.2",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.trim": "^1.2.9",
+ "string.prototype.trimend": "^1.0.8",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.2",
+ "typed-array-byte-length": "^1.0.1",
+ "typed-array-byte-offset": "^1.0.2",
+ "typed-array-length": "^1.0.6",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.15"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.0.19",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz",
+ "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.3",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.3",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.7",
+ "iterator.prototype": "^1.1.2",
+ "safe-array-concat": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz",
+ "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
+ "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz",
+ "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.23.0",
+ "@esbuild/android-arm": "0.23.0",
+ "@esbuild/android-arm64": "0.23.0",
+ "@esbuild/android-x64": "0.23.0",
+ "@esbuild/darwin-arm64": "0.23.0",
+ "@esbuild/darwin-x64": "0.23.0",
+ "@esbuild/freebsd-arm64": "0.23.0",
+ "@esbuild/freebsd-x64": "0.23.0",
+ "@esbuild/linux-arm": "0.23.0",
+ "@esbuild/linux-arm64": "0.23.0",
+ "@esbuild/linux-ia32": "0.23.0",
+ "@esbuild/linux-loong64": "0.23.0",
+ "@esbuild/linux-mips64el": "0.23.0",
+ "@esbuild/linux-ppc64": "0.23.0",
+ "@esbuild/linux-riscv64": "0.23.0",
+ "@esbuild/linux-s390x": "0.23.0",
+ "@esbuild/linux-x64": "0.23.0",
+ "@esbuild/netbsd-x64": "0.23.0",
+ "@esbuild/openbsd-arm64": "0.23.0",
+ "@esbuild/openbsd-x64": "0.23.0",
+ "@esbuild/sunos-x64": "0.23.0",
+ "@esbuild/win32-arm64": "0.23.0",
+ "@esbuild/win32-ia32": "0.23.0",
+ "@esbuild/win32-x64": "0.23.0"
+ }
+ },
+ "node_modules/esbuild-plugins-node-modules-polyfill": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/esbuild-plugins-node-modules-polyfill/-/esbuild-plugins-node-modules-polyfill-1.6.4.tgz",
+ "integrity": "sha512-x3MCOvZrKDGAfqAYS/pZUUSwiN+XH7x84A+Prup0CZBJKuGfuGkTAC4g01D6JPs/GCM9wzZVfd8bmiy+cP/iXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jspm/core": "^2.0.1",
+ "local-pkg": "^0.5.0",
+ "resolve.exports": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "esbuild": "^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.7.0.tgz",
+ "integrity": "sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.11.0",
+ "@eslint/config-array": "^0.17.0",
+ "@eslint/eslintrc": "^3.1.0",
+ "@eslint/js": "9.7.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.3.0",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.0.2",
+ "eslint-visitor-keys": "^4.0.0",
+ "espree": "^10.1.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import-x": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-0.5.1.tgz",
+ "integrity": "sha512-2JK8bbFOLes+gG6tgdnM8safCxMAj4u2wjX8X1BRFPfnY7Ct2hFYESoIcVwABX/DDcdpQFLGtKmzbNEWJZD9iQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/utils": "^7.4.0",
+ "debug": "^4.3.4",
+ "doctrine": "^3.0.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "get-tsconfig": "^4.7.3",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.3",
+ "semver": "^7.6.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0 || ^9.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-jest-dom": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-5.4.0.tgz",
+ "integrity": "sha512-yBqvFsnpS5Sybjoq61cJiUsenRkC9K32hYQBFS9doBR7nbQZZ5FyO+X7MlmfM1C48Ejx/qTuOCgukDUNyzKZ7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.16.3",
+ "requireindex": "^1.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0",
+ "npm": ">=6",
+ "yarn": ">=1"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": "^8.0.0 || ^9.0.0 || ^10.0.0",
+ "eslint": "^6.8.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@testing-library/dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.34.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz",
+ "integrity": "sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.2",
+ "array.prototype.toreversed": "^1.1.2",
+ "array.prototype.tosorted": "^1.1.3",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.0.19",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.8",
+ "object.fromentries": "^2.0.8",
+ "object.hasown": "^1.1.4",
+ "object.values": "^1.2.0",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.11"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz",
+ "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.2.tgz",
+ "integrity": "sha512-1E94YOTUDnOjSLyvOwmbVDzQi/WkKm3WVrMXu6SmBr6DN95xTGZmI6HJ/eOkSXh/DlheRsxaPsJvZByDBhWLVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/utils": "^5.58.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "eslint": "^7.5.0 || ^8.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
+ "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/types": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
+ "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
+ "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/visitor-keys": "5.62.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/utils": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
+ "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.62.0",
+ "@typescript-eslint/types": "5.62.0",
+ "@typescript-eslint/typescript-estree": "5.62.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.62.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
+ "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "5.62.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-plugin-testing-library/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint-plugin-vitest": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.5.4.tgz",
+ "integrity": "sha512-um+odCkccAHU53WdKAw39MY61+1x990uXjSPguUCq3VcEHdqJrOb8OTMrbYlY6f9jAKx7x98kLVlIe3RJeJqoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/utils": "^7.7.1"
+ },
+ "engines": {
+ "node": "^18.0.0 || >= 20.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "vitest": "*"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/eslint-plugin": {
+ "optional": true
+ },
+ "vitest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz",
+ "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
+ "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
+ "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.12.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estree-util-attach-comments": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-2.1.1.tgz",
+ "integrity": "sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-build-jsx": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-2.2.2.tgz",
+ "integrity": "sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "estree-util-is-identifier-name": "^2.0.0",
+ "estree-walker": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-is-identifier-name": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.1.0.tgz",
+ "integrity": "sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-to-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-1.2.0.tgz",
+ "integrity": "sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "astring": "^1.8.0",
+ "source-map": "^0.7.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-util-value-to-estree": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz",
+ "integrity": "sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-plain-obj": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/estree-util-value-to-estree/node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/estree-util-visit": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz",
+ "integrity": "sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/eval": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz",
+ "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "require-like": ">= 0.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/execa": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz",
+ "integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==",
+ "license": "MIT",
+ "dependencies": {
+ "@sindresorhus/merge-streams": "^4.0.0",
+ "cross-spawn": "^7.0.3",
+ "figures": "^6.1.0",
+ "get-stream": "^9.0.0",
+ "human-signals": "^7.0.0",
+ "is-plain-obj": "^4.1.0",
+ "is-stream": "^4.0.1",
+ "npm-run-path": "^5.2.0",
+ "pretty-ms": "^9.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-final-newline": "^4.0.0",
+ "yoctocolors": "^2.0.0"
+ },
+ "engines": {
+ "node": "^18.19.0 || >=20.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execa/node_modules/parse-ms": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
+ "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/execa/node_modules/pretty-ms": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz",
+ "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==",
+ "license": "MIT",
+ "dependencies": {
+ "parse-ms": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/exit-hook": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz",
+ "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "license": "(MIT OR WTFPL)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.19.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
+ "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.2",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.6.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/express-rate-limit": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.3.1.tgz",
+ "integrity": "sha512-BbaryvkY4wEgDqLgD18/NSy2lDO2jTuT9Y8c1Mpx0X63Yz0sYd5zN6KPe7UvpuSVvV33T6RaE1o1IVZQjHMYgw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": "4 || 5 || ^5.0.0-beta.1"
+ }
+ },
+ "node_modules/express/node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/express/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/express/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-url-parser": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz",
+ "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^1.3.2"
+ }
+ },
+ "node_modules/fast-url-parser/node_modules/punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fault": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz",
+ "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "format": "^0.2.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/figures": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz",
+ "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-unicode-supported": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "license": "MIT"
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/format": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
+ "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
+ "node_modules/fs-extra": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
+ "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
+ "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generic-names": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz",
+ "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "loader-utils": "^3.2.0"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-func-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
+ "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/get-port": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz",
+ "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-stdin": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
+ "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sec-ant/readable-stream": "^0.4.1",
+ "is-stream": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+ "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.7.5",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz",
+ "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "license": "MIT"
+ },
+ "node_modules/glob": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
+ "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^4.0.1",
+ "minimatch": "^10.0.0",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+ "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "15.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.4.0.tgz",
+ "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/graphql": {
+ "version": "16.8.1",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
+ "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
+ }
+ },
+ "node_modules/gunzip-maybe": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz",
+ "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserify-zlib": "^0.1.4",
+ "is-deflate": "^1.0.0",
+ "is-gzip": "^1.0.0",
+ "peek-stream": "^1.1.0",
+ "pumpify": "^1.3.3",
+ "through2": "^2.0.3"
+ },
+ "bin": {
+ "gunzip-maybe": "bin.js"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hast-util-to-estree": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz",
+ "integrity": "sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^2.0.0",
+ "@types/unist": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "estree-util-attach-comments": "^2.0.0",
+ "estree-util-is-identifier-name": "^2.0.0",
+ "hast-util-whitespace": "^2.0.0",
+ "mdast-util-mdx-expression": "^1.0.0",
+ "mdast-util-mdxjs-esm": "^1.0.0",
+ "property-information": "^6.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-object": "^0.4.1",
+ "unist-util-position": "^4.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz",
+ "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/headers-polyfill": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz",
+ "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/helmet": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz",
+ "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz",
+ "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^7.5.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/html-encoding-sniffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
+ "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/html-to-text": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
+ "integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
+ "license": "MIT",
+ "dependencies": {
+ "@selderee/plugin-htmlparser2": "^0.11.0",
+ "deepmerge": "^4.3.1",
+ "dom-serializer": "^2.0.0",
+ "htmlparser2": "^8.0.2",
+ "selderee": "^0.11.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz",
+ "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/icss-utils": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
+ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-in-the-middle": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.9.1.tgz",
+ "integrity": "sha512-E+3tEOutU1MV0mxhuCwfSPNNWRkbTJ3/YyL5be+blNIbHwZc53uYHQfuIhAU77xWR0BoF2eT7cqDJ6VlU5APPg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-attributes": "^1.9.5",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
+ "node_modules/inline-style-parser": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
+ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/input-otp": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.2.4.tgz",
+ "integrity": "sha512-md6rhmD+zmMnUh5crQNSQxq3keBRYvE3odbr4Qb9g2NWzQv9azi+t1a3X4TBTbh98fsGHgEEJlzbe1q860uGCA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/intl-parse-accept-language": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/intl-parse-accept-language/-/intl-parse-accept-language-1.0.0.tgz",
+ "integrity": "sha512-YFMSV91JNBOSjw1cOfw2tup6hDP7mkz+2AUV7W1L1AM6ntgI75qC1ZeFpjPGMrWp+upmBRTX2fJWQ8c7jsUWpA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+ "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^2.0.0",
+ "is-decimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-async-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+ "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+ "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
+ "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-decimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+ "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-deflate": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz",
+ "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+ "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "license": "MIT",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-gzip": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz",
+ "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-hexadecimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-node-process": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz",
+ "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-port-reachable": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz",
+ "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-reference": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz",
+ "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
+ "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+ "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz",
+ "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz",
+ "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isbot": {
+ "version": "5.1.13",
+ "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.13.tgz",
+ "integrity": "sha512-RXtBib4m9zChSb+187EpNQML7Z3u2i34zDdqcRFZnqSJs0xdh91xzJytc5apYVg+9Y4NGnUQ0AIeJvX9FAnCUw==",
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
+ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.23",
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+ "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "reflect.getprototypeof": "^1.0.4",
+ "set-function-name": "^2.0.1"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz",
+ "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/javascript-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz",
+ "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jiti": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
+ "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-beautify": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz",
+ "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==",
+ "license": "MIT",
+ "dependencies": {
+ "config-chain": "^1.1.13",
+ "editorconfig": "^1.0.4",
+ "glob": "^10.3.3",
+ "js-cookie": "^3.0.5",
+ "nopt": "^7.2.0"
+ },
+ "bin": {
+ "css-beautify": "js/bin/css-beautify.js",
+ "html-beautify": "js/bin/html-beautify.js",
+ "js-beautify": "js/bin/js-beautify.js"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/js-beautify/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/js-beautify/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/js-beautify/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/js-beautify/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/js-cookie": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
+ "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsdom": {
+ "version": "24.1.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz",
+ "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssstyle": "^4.0.1",
+ "data-urls": "^5.0.0",
+ "decimal.js": "^10.4.3",
+ "form-data": "^4.0.0",
+ "html-encoding-sniffer": "^4.0.0",
+ "http-proxy-agent": "^7.0.2",
+ "https-proxy-agent": "^7.0.4",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.10",
+ "parse5": "^7.1.2",
+ "rrweb-cssom": "^0.7.0",
+ "saxes": "^6.0.0",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.1.4",
+ "w3c-xmlserializer": "^5.0.0",
+ "webidl-conversions": "^7.0.0",
+ "whatwg-encoding": "^3.1.1",
+ "whatwg-mimetype": "^4.0.0",
+ "whatwg-url": "^14.0.0",
+ "ws": "^8.17.0",
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "canvas": "^2.11.2"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsdom/node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/jsdom/node_modules/https-proxy-agent": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz",
+ "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/jsdom/node_modules/ws": {
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz",
+ "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz",
+ "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsox": {
+ "version": "1.2.119",
+ "resolved": "https://registry.npmjs.org/jsox/-/jsox-1.2.119.tgz",
+ "integrity": "sha512-f37obwxWKKuylcaOzNlUlzfDvURSCpqTXs8yEivhvsp86D/DTIySxP4v5Qdlg24qCuzDSZ0mJr3krc/f7TZ/5A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsox": "lib/cli.js"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leac": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
+ "integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
+ "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "license": "MIT"
+ },
+ "node_modules/litefs-js": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/litefs-js/-/litefs-js-1.1.2.tgz",
+ "integrity": "sha512-XKhntdOq8ZXoWbdmANu+PrmJBbf4aIUaHq0356IIk+Uw213evsfg1eNfU0aD04tbF4KXknvG4MWD8sp3D825zg==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^0.5.0"
+ }
+ },
+ "node_modules/litefs-js/node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/load-json-file/node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/loader-utils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.2.tgz",
+ "integrity": "sha512-vjJi4vQDasD8t0kMpxe+9URAcgbSuASqoj/Wuk3MawTk97LYa2KfdHreAkd1G/pmPLMvzZEw7/OsydADNemerQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12.13.0"
+ }
+ },
+ "node_modules/local-pkg": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
+ "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mlly": "^1.4.2",
+ "pkg-types": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "license": "MIT"
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/log-symbols/node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/longest-streak": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+ "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz",
+ "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-func-name": "^2.0.1"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz",
+ "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==",
+ "license": "ISC",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/lz-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
+ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "lz-string": "bin/bin.js"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.8",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
+ "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/magicast": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz",
+ "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.24.4",
+ "@babel/types": "^7.24.0",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/markdown-extensions": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz",
+ "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/marked": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-7.0.4.tgz",
+ "integrity": "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==",
+ "license": "MIT",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 16"
+ }
+ },
+ "node_modules/md-to-react-email": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/md-to-react-email/-/md-to-react-email-5.0.2.tgz",
+ "integrity": "sha512-x6kkpdzIzUhecda/yahltfEl53mH26QdWu4abUF9+S0Jgam8P//Ciro8cdhyMHnT5MQUJYrIbO6ORM2UxPiNNA==",
+ "license": "MIT",
+ "dependencies": {
+ "marked": "7.0.4"
+ },
+ "peerDependencies": {
+ "react": "18.x"
+ }
+ },
+ "node_modules/mdast-util-definitions": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
+ "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "unist-util-visit": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-from-markdown": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz",
+ "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "mdast-util-to-string": "^3.1.0",
+ "micromark": "^3.0.0",
+ "micromark-util-decode-numeric-character-reference": "^1.0.0",
+ "micromark-util-decode-string": "^1.0.0",
+ "micromark-util-normalize-identifier": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "uvu": "^0.5.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-frontmatter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-1.0.1.tgz",
+ "integrity": "sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-markdown": "^1.3.0",
+ "micromark-extension-frontmatter": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-2.0.1.tgz",
+ "integrity": "sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-from-markdown": "^1.0.0",
+ "mdast-util-mdx-expression": "^1.0.0",
+ "mdast-util-mdx-jsx": "^2.0.0",
+ "mdast-util-mdxjs-esm": "^1.0.0",
+ "mdast-util-to-markdown": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-expression": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.2.tgz",
+ "integrity": "sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^2.0.0",
+ "@types/mdast": "^3.0.0",
+ "mdast-util-from-markdown": "^1.0.0",
+ "mdast-util-to-markdown": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-jsx": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.4.tgz",
+ "integrity": "sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^2.0.0",
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "ccount": "^2.0.0",
+ "mdast-util-from-markdown": "^1.1.0",
+ "mdast-util-to-markdown": "^1.3.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-remove-position": "^4.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdxjs-esm": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.1.tgz",
+ "integrity": "sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^2.0.0",
+ "@types/mdast": "^3.0.0",
+ "mdast-util-from-markdown": "^1.0.0",
+ "mdast-util-to-markdown": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-phrasing": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz",
+ "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "12.3.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz",
+ "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "@types/mdast": "^3.0.0",
+ "mdast-util-definitions": "^5.0.0",
+ "micromark-util-sanitize-uri": "^1.1.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-generated": "^2.0.0",
+ "unist-util-position": "^4.0.0",
+ "unist-util-visit": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-markdown": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz",
+ "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^3.0.0",
+ "mdast-util-to-string": "^3.0.0",
+ "micromark-util-decode-string": "^1.0.0",
+ "unist-util-visit": "^4.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz",
+ "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/media-query-parser": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/media-query-parser/-/media-query-parser-2.0.2.tgz",
+ "integrity": "sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+ "license": "MIT"
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromark": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz",
+ "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-core-commonmark": "^1.0.1",
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-combine-extensions": "^1.0.0",
+ "micromark-util-decode-numeric-character-reference": "^1.0.0",
+ "micromark-util-encode": "^1.0.0",
+ "micromark-util-normalize-identifier": "^1.0.0",
+ "micromark-util-resolve-all": "^1.0.0",
+ "micromark-util-sanitize-uri": "^1.0.0",
+ "micromark-util-subtokenize": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.1",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-core-commonmark": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz",
+ "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-factory-destination": "^1.0.0",
+ "micromark-factory-label": "^1.0.0",
+ "micromark-factory-space": "^1.0.0",
+ "micromark-factory-title": "^1.0.0",
+ "micromark-factory-whitespace": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-classify-character": "^1.0.0",
+ "micromark-util-html-tag-name": "^1.0.0",
+ "micromark-util-normalize-identifier": "^1.0.0",
+ "micromark-util-resolve-all": "^1.0.0",
+ "micromark-util-subtokenize": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.1",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-extension-frontmatter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-1.1.1.tgz",
+ "integrity": "sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fault": "^2.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-expression": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.8.tgz",
+ "integrity": "sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "micromark-factory-mdx-expression": "^1.0.0",
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-events-to-acorn": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-extension-mdx-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.5.tgz",
+ "integrity": "sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/acorn": "^4.0.0",
+ "@types/estree": "^1.0.0",
+ "estree-util-is-identifier-name": "^2.0.0",
+ "micromark-factory-mdx-expression": "^1.0.0",
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "uvu": "^0.5.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdx-md": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.1.tgz",
+ "integrity": "sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdxjs": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.1.tgz",
+ "integrity": "sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.0.0",
+ "acorn-jsx": "^5.0.0",
+ "micromark-extension-mdx-expression": "^1.0.0",
+ "micromark-extension-mdx-jsx": "^1.0.0",
+ "micromark-extension-mdx-md": "^1.0.0",
+ "micromark-extension-mdxjs-esm": "^1.0.0",
+ "micromark-util-combine-extensions": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-extension-mdxjs-esm": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.5.tgz",
+ "integrity": "sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "micromark-core-commonmark": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-events-to-acorn": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "unist-util-position-from-estree": "^1.1.0",
+ "uvu": "^0.5.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/micromark-factory-destination": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
+ "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-factory-label": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz",
+ "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-factory-mdx-expression": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.9.tgz",
+ "integrity": "sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-events-to-acorn": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "unist-util-position-from-estree": "^1.0.0",
+ "uvu": "^0.5.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "node_modules/micromark-factory-space": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz",
+ "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-factory-title": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz",
+ "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-factory-whitespace": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz",
+ "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz",
+ "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-chunked": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz",
+ "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-classify-character": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz",
+ "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-combine-extensions": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz",
+ "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-numeric-character-reference": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz",
+ "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-string": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz",
+ "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-decode-numeric-character-reference": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz",
+ "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-events-to-acorn": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.3.tgz",
+ "integrity": "sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/acorn": "^4.0.0",
+ "@types/estree": "^1.0.0",
+ "@types/unist": "^2.0.0",
+ "estree-util-visit": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "uvu": "^0.5.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "node_modules/micromark-util-html-tag-name": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz",
+ "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-normalize-identifier": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz",
+ "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-resolve-all": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz",
+ "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz",
+ "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^1.0.0",
+ "micromark-util-encode": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0"
+ }
+ },
+ "node_modules/micromark-util-subtokenize": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz",
+ "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-chunked": "^1.0.0",
+ "micromark-util-symbol": "^1.0.0",
+ "micromark-util-types": "^1.0.0",
+ "uvu": "^0.5.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz",
+ "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz",
+ "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
+ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-collect/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-flush/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "license": "MIT"
+ },
+ "node_modules/mlly": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.0.tgz",
+ "integrity": "sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.3",
+ "pathe": "^1.1.2",
+ "pkg-types": "^1.1.0",
+ "ufo": "^1.5.3"
+ }
+ },
+ "node_modules/modern-ahocorasick": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/modern-ahocorasick/-/modern-ahocorasick-1.0.1.tgz",
+ "integrity": "sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/module-details-from-path": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz",
+ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==",
+ "license": "MIT"
+ },
+ "node_modules/moo": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
+ "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/morgan": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
+ "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "basic-auth": "~2.0.1",
+ "debug": "2.6.9",
+ "depd": "~2.0.0",
+ "on-finished": "~2.3.0",
+ "on-headers": "~1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/morgan/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/morgan/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/morgan/node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mrmime": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
+ "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "license": "MIT"
+ },
+ "node_modules/msw": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.1.tgz",
+ "integrity": "sha512-ocgvBCLn/5l3jpl1lssIb3cniuACJLoOfZu01e3n5dbJrpA5PeeWn28jCLgQDNt6d7QT8tF2fYRzm9JoEHtiig==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@bundled-es-modules/cookie": "^2.0.0",
+ "@bundled-es-modules/statuses": "^1.0.1",
+ "@inquirer/confirm": "^3.0.0",
+ "@mswjs/cookies": "^1.1.0",
+ "@mswjs/interceptors": "^0.29.0",
+ "@open-draft/until": "^2.1.0",
+ "@types/cookie": "^0.6.0",
+ "@types/statuses": "^2.0.4",
+ "chalk": "^4.1.2",
+ "graphql": "^16.8.1",
+ "headers-polyfill": "^4.0.2",
+ "is-node-process": "^1.2.0",
+ "outvariant": "^1.4.2",
+ "path-to-regexp": "^6.2.0",
+ "strict-event-emitter": "^0.5.1",
+ "type-fest": "^4.9.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "msw": "cli/index.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mswjs"
+ },
+ "peerDependencies": {
+ "typescript": ">= 4.7.x"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/msw/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/msw/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/msw/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/msw/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/msw/node_modules/path-to-regexp": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz",
+ "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nearley": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
+ "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^2.19.0",
+ "moo": "^0.5.0",
+ "railroad-diagrams": "^1.0.0",
+ "randexp": "0.4.6"
+ },
+ "bin": {
+ "nearley-railroad": "bin/nearley-railroad.js",
+ "nearley-test": "bin/nearley-test.js",
+ "nearley-unparse": "bin/nearley-unparse.js",
+ "nearleyc": "bin/nearleyc.js"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://nearley.js.org/#give-to-nearley"
+ }
+ },
+ "node_modules/nearley/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-abi": {
+ "version": "3.62.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.62.0.tgz",
+ "integrity": "sha512-CPMcGa+y33xuL1E0TcNIu4YyaZCxnnvkVaEXrsosR3FxN+fV8xvb7Mzpb7IgKler10qeMkE6+Dp8qJhpzdq35g==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch/node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT"
+ },
+ "node_modules/node-fetch/node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/node-fetch/node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/node-html-parser": {
+ "version": "6.1.13",
+ "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz",
+ "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "css-select": "^5.1.0",
+ "he": "1.2.0"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
+ "license": "MIT"
+ },
+ "node_modules/node-sql-parser": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-4.18.0.tgz",
+ "integrity": "sha512-2YEOR5qlI1zUFbGMLKNfsrR5JUvFg9LxIRVE+xJe962pfVLH0rnItqLzv96XVs1Y1UIR8FxsXAuvX/lYAWZ2BQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "big-integer": "^1.6.48"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
+ "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^2.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/normalize-package-data": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz",
+ "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "hosted-git-info": "^6.0.0",
+ "is-core-module": "^2.8.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-install-checks": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz",
+ "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "semver": "^7.1.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-normalize-package-bin": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
+ "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-package-arg": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz",
+ "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "hosted-git-info": "^6.0.0",
+ "proc-log": "^3.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-pick-manifest": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz",
+ "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "npm-install-checks": "^6.0.0",
+ "npm-normalize-package-bin": "^3.0.0",
+ "npm-package-arg": "^10.0.0",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-run-all": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
+ "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "chalk": "^2.4.1",
+ "cross-spawn": "^6.0.5",
+ "memorystream": "^0.3.1",
+ "minimatch": "^3.0.4",
+ "pidtree": "^0.3.0",
+ "read-pkg": "^3.0.0",
+ "shell-quote": "^1.6.1",
+ "string.prototype.padend": "^3.0.0"
+ },
+ "bin": {
+ "npm-run-all": "bin/npm-run-all/index.js",
+ "run-p": "bin/run-p/index.js",
+ "run-s": "bin/run-s/index.js"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/pidtree": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
+ "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-all/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+ "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.10",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz",
+ "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
+ "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.hasown": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz",
+ "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
+ "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/opentelemetry-instrumentation-fetch-node": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/opentelemetry-instrumentation-fetch-node/-/opentelemetry-instrumentation-fetch-node-1.2.3.tgz",
+ "integrity": "sha512-Qb11T7KvoCevMaSeuamcLsAD+pZnavkhDnlVL0kRozfhl42dKG5Q3anUklAFKJZjY3twLR+BnRa6DlwwkIE/+A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.17.0"
+ },
+ "engines": {
+ "node": ">18.0.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.6.0"
+ }
+ },
+ "node_modules/opentelemetry-instrumentation-fetch-node/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz",
+ "integrity": "sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/opentelemetry-instrumentation-fetch-node/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz",
+ "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/opentelemetry-instrumentation-remix": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/opentelemetry-instrumentation-remix/-/opentelemetry-instrumentation-remix-0.7.1.tgz",
+ "integrity": "sha512-zzJ8CAsf4Pem+B1zY0NEKQcQjXIORgylPBIQMO2x1OdRc9HzBPLUp7JIlGt/RAfPsp5qaEs7QqvX9xtsrZgtFQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.43.0",
+ "@opentelemetry/semantic-conventions": "^1.17.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/opentelemetry-instrumentation-remix/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.43.0",
+ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.43.0.tgz",
+ "integrity": "sha512-S1uHE+sxaepgp+t8lvIDuRgyjJWisAb733198kwQTUc9ZtYQ2V2gmyCtR1x21ePGVLoMiX/NWY7WA290hwkjJQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/opentelemetry-instrumentation-remix/node_modules/import-in-the-middle": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz",
+ "integrity": "sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ora/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/ora/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/ora/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/ora/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ora/node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/outdent": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.8.0.tgz",
+ "integrity": "sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/outvariant": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.2.tgz",
+ "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
+ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-entities": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz",
+ "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "character-entities": "^2.0.0",
+ "character-entities-legacy": "^3.0.0",
+ "character-reference-invalid": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0",
+ "is-hexadecimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse-json/node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/parse-ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
+ "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parseley": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
+ "integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
+ "license": "MIT",
+ "dependencies": {
+ "leac": "^0.6.0",
+ "peberminta": "^0.9.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==",
+ "dev": true,
+ "license": "(WTFPL OR MIT)"
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
+ },
+ "node_modules/path-scurry": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+ "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
+ "license": "MIT"
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pathe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pathval": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
+ "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
+ "node_modules/peberminta": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
+ "integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
+ "node_modules/peek-stream": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz",
+ "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "duplexify": "^3.5.0",
+ "through2": "^2.0.3"
+ }
+ },
+ "node_modules/periscopic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz",
+ "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^3.0.0",
+ "is-reference": "^3.0.0"
+ }
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz",
+ "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==",
+ "license": "MIT"
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-types": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz",
+ "integrity": "sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "confbox": "^0.1.7",
+ "mlly": "^1.7.0",
+ "pathe": "^1.1.2"
+ }
+ },
+ "node_modules/playwright": {
+ "version": "1.45.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz",
+ "integrity": "sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "playwright-core": "1.45.2"
+ },
+ "bin": {
+ "playwright": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/playwright-core": {
+ "version": "1.45.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.2.tgz",
+ "integrity": "sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "playwright-core": "cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/playwright/node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
+ "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
+ "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.1",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-discard-duplicates": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
+ "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-modules": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-6.0.0.tgz",
+ "integrity": "sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "generic-names": "^4.0.0",
+ "icss-utils": "^5.1.0",
+ "lodash.camelcase": "^4.3.0",
+ "postcss-modules-extract-imports": "^3.0.0",
+ "postcss-modules-local-by-default": "^4.0.0",
+ "postcss-modules-scope": "^3.0.0",
+ "postcss-modules-values": "^4.0.0",
+ "string-hash": "^1.1.1"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-modules-extract-imports": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
+ "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-local-by-default": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz",
+ "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "icss-utils": "^5.0.0",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.1.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-scope": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz",
+ "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.4"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-values": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "icss-utils": "^5.0.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
+ "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.11"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
+ "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "license": "MIT"
+ },
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
+ "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-plugin-sql": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-sql/-/prettier-plugin-sql-0.18.1.tgz",
+ "integrity": "sha512-2+Nob2sg7hzLAKJoE6sfgtkhBZCqOzrWHZPvE4Kee/e80oOyI4qwy9vypeltqNBJwTtq3uiKPrCxlT03bBpOaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jsox": "^1.2.119",
+ "node-sql-parser": "^4.12.0",
+ "sql-formatter": "^15.0.2",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ },
+ "peerDependencies": {
+ "prettier": "^3.0.3"
+ }
+ },
+ "node_modules/prettier-plugin-tailwindcss": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.5.tgz",
+ "integrity": "sha512-axfeOArc/RiGHjOIy9HytehlC0ZLeMaqY09mm8YCkMzznKiDkwFzOpBvtuhuv3xG5qB73+Mj7OCe2j/L1ryfuQ==",
+ "dev": true,
+ "license": "MIT",
+ "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-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-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
+ }
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/pretty-format/node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pretty-ms": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
+ "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parse-ms": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/prisma": {
+ "version": "5.17.0",
+ "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.17.0.tgz",
+ "integrity": "sha512-m4UWkN5lBE6yevqeOxEvmepnL5cNPEjzMw2IqDB59AcEV6w7D8vGljDLd1gPFH+W6gUxw9x7/RmN5dCS/WTPxA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@prisma/engines": "5.17.0"
+ },
+ "bin": {
+ "prisma": "build/index.js"
+ },
+ "engines": {
+ "node": ">=16.13"
+ }
+ },
+ "node_modules/prismjs": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
+ "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/proc-log": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz",
+ "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/property-information": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz",
+ "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+ "license": "ISC"
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "node_modules/pumpify/node_modules/pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qrcode": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
+ "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
+ "license": "MIT",
+ "dependencies": {
+ "dijkstrajs": "^1.0.1",
+ "encode-utf8": "^1.0.3",
+ "pngjs": "^5.0.0",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "qrcode": "bin/qrcode"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/qrcode/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/qrcode/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/qrcode/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/qrcode/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "license": "ISC"
+ },
+ "node_modules/qrcode/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/railroad-diagrams": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+ "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/randexp": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+ "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "discontinuous-range": "1.0.0",
+ "ret": "~0.1.10"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/raw-body/node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
+ "node_modules/react-promise-suspense": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.4.tgz",
+ "integrity": "sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^2.0.1"
+ }
+ },
+ "node_modules/react-promise-suspense/node_modules/fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==",
+ "license": "MIT"
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-remove-scroll": {
+ "version": "2.5.7",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz",
+ "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-remove-scroll-bar": "^2.3.4",
+ "react-style-singleton": "^2.2.1",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.0",
+ "use-sidecar": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
+ "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
+ "license": "MIT",
+ "dependencies": {
+ "react-style-singleton": "^2.2.1",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.0.tgz",
+ "integrity": "sha512-bziKjCcDbcxgWS9WlWFcQIVZ2vJHnCP6DGpQDT0l+0PFDasfJKgzf9CM22eTyhFsZkjk8ApCdKjJwKtzqH80jQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.18.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.0.tgz",
+ "integrity": "sha512-BhcczgDWWgvGZxjDDGuGHrA8HrsSudilqTaRSBYLWDayvo1ClchNIDVt5rldqp6e7Dro5dEFx9Mzc+r292lN0w==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.18.0",
+ "react-router": "6.25.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-style-singleton": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
+ "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==",
+ "license": "MIT",
+ "dependencies": {
+ "get-nonce": "^1.0.0",
+ "invariant": "^2.2.4",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/read-cache/node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg/node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/read-pkg/node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/read-pkg/node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/read-pkg/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
+ "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.1",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "which-builtin-type": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
+ "license": "MIT"
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
+ "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/registry-auth-token": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
+ "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/registry-url": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
+ "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "rc": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/remark-frontmatter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-4.0.1.tgz",
+ "integrity": "sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-frontmatter": "^1.0.0",
+ "micromark-extension-frontmatter": "^1.0.0",
+ "unified": "^10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.3.0.tgz",
+ "integrity": "sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdast-util-mdx": "^2.0.0",
+ "micromark-extension-mdxjs": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx-frontmatter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/remark-mdx-frontmatter/-/remark-mdx-frontmatter-1.1.1.tgz",
+ "integrity": "sha512-7teX9DW4tI2WZkXS4DBxneYSY7NHiXl4AKdWDO9LXVweULlCT8OPWsOjLEnMIXViN1j+QcY8mfbq3k0EK6x3uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "estree-util-is-identifier-name": "^1.0.0",
+ "estree-util-value-to-estree": "^1.0.0",
+ "js-yaml": "^4.0.0",
+ "toml": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=12.2.0"
+ }
+ },
+ "node_modules/remark-mdx-frontmatter/node_modules/estree-util-is-identifier-name": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-1.1.0.tgz",
+ "integrity": "sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/remark-parse": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz",
+ "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-from-markdown": "^1.0.0",
+ "unified": "^10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-rehype": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz",
+ "integrity": "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^2.0.0",
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-hast": "^12.1.0",
+ "unified": "^10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remix-auth": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/remix-auth/-/remix-auth-3.7.0.tgz",
+ "integrity": "sha512-2QVjp2nJVaYxuFBecMQwzixCO7CLSssttLBU5eVlNcNlVeNMmY1g7OkmZ1Ogw9sBcoMXZ18J7xXSK0AISVFcfQ==",
+ "dependencies": {
+ "uuid": "^8.3.2"
+ },
+ "peerDependencies": {
+ "@remix-run/react": "^1.0.0 || ^2.0.0",
+ "@remix-run/server-runtime": "^1.0.0 || ^2.0.0"
+ }
+ },
+ "node_modules/remix-auth-github": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/remix-auth-github/-/remix-auth-github-1.7.0.tgz",
+ "integrity": "sha512-xuy/DW44y/eWU+vUsf9NlQUtLhayMZEJszgaVr1txwjA0OzpPee5qNxPQ9RBg8WdnY3pMWck5m070MW5Jt7nxg==",
+ "license": "MIT",
+ "dependencies": {
+ "remix-auth-oauth2": "^1.11.2"
+ },
+ "peerDependencies": {
+ "@remix-run/server-runtime": "^1.0.0 || ^2.0.0",
+ "remix-auth": "^3.4.0"
+ }
+ },
+ "node_modules/remix-auth-oauth2": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/remix-auth-oauth2/-/remix-auth-oauth2-1.11.2.tgz",
+ "integrity": "sha512-5ORP+LMi5CVCA/Wb8Z+FCAJ73Uiy4uyjEzhlVwNBfdAkPOnfxzoi+q/pY/CrueYv3OniCXRM35ZYqkVi3G1UPw==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "uuid": "^9.0.1"
+ },
+ "peerDependencies": {
+ "@remix-run/server-runtime": "^1.0.0 || ^2.0.0",
+ "remix-auth": "^3.6.0"
+ }
+ },
+ "node_modules/remix-auth-oauth2/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/remix-flat-routes": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/remix-flat-routes/-/remix-flat-routes-0.6.5.tgz",
+ "integrity": "sha512-VvPak+LCxL4Fm6Kb/nqPLipB71k9p+GXpzRNPVxs9FmCeJ7hxVmQ3HQMpStzuRQyAh0PMkaX6mBiRlCRHTCYHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/v1-route-convention": "^0.1.3",
+ "fs-extra": "^11.1.1",
+ "minimatch": "^5.1.0"
+ },
+ "bin": {
+ "migrate-flat-routes": "dist/cli.js"
+ },
+ "peerDependencies": {
+ "@remix-run/dev": "^1.15.0 || ^2"
+ }
+ },
+ "node_modules/remix-flat-routes/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/remix-ssg": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/remix-ssg/-/remix-ssg-0.0.8.tgz",
+ "integrity": "sha512-t+Pe5HzQYiTKocyvvmtQDwPllYSeCuWVw0StPzyBxjP5EZnIFsYjrRQSRqEGo0uvC7bGB1FxoIYlmuzKB9u6+w==",
+ "dev": true,
+ "dependencies": {
+ "htmlparser2": "^8.0.1"
+ },
+ "bin": {
+ "remix-ssg": "bin/remix-ssg.cjs"
+ },
+ "peerDependencies": {
+ "@remix-run/dev": ">=1",
+ "@remix-run/node": ">=1",
+ "react-router-dom": "*"
+ }
+ },
+ "node_modules/remix-utils": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/remix-utils/-/remix-utils-7.6.0.tgz",
+ "integrity": "sha512-BPhCUEy+nwrhDDDg2v3+LFSszV6tluMbeSkbffj2o4tqZxt5Kn69Y9sNpGxYLAj8gjqeYDuxjv55of+gYnnykA==",
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^4.3.3"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@remix-run/cloudflare": "^2.0.0",
+ "@remix-run/deno": "^2.0.0",
+ "@remix-run/node": "^2.0.0",
+ "@remix-run/react": "^2.0.0",
+ "@remix-run/router": "^1.7.2",
+ "crypto-js": "^4.1.1",
+ "intl-parse-accept-language": "^1.0.0",
+ "is-ip": "^5.0.1",
+ "react": "^18.0.0",
+ "zod": "^3.22.4"
+ },
+ "peerDependenciesMeta": {
+ "@remix-run/cloudflare": {
+ "optional": true
+ },
+ "@remix-run/deno": {
+ "optional": true
+ },
+ "@remix-run/node": {
+ "optional": true
+ },
+ "@remix-run/react": {
+ "optional": true
+ },
+ "@remix-run/router": {
+ "optional": true
+ },
+ "crypto-js": {
+ "optional": true
+ },
+ "intl-parse-accept-language": {
+ "optional": true
+ },
+ "is-ip": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-in-the-middle": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.3.0.tgz",
+ "integrity": "sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "module-details-from-path": "^1.0.3",
+ "resolve": "^1.22.1"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/require-like": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz",
+ "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "license": "ISC"
+ },
+ "node_modules/requireindex": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
+ "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.5"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.18.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz",
+ "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.5"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.18.0",
+ "@rollup/rollup-android-arm64": "4.18.0",
+ "@rollup/rollup-darwin-arm64": "4.18.0",
+ "@rollup/rollup-darwin-x64": "4.18.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.18.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.18.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.18.0",
+ "@rollup/rollup-linux-arm64-musl": "4.18.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.18.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.18.0",
+ "@rollup/rollup-linux-x64-gnu": "4.18.0",
+ "@rollup/rollup-linux-x64-musl": "4.18.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.18.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.18.0",
+ "@rollup/rollup-win32-x64-msvc": "4.18.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rrweb-cssom": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.0.tgz",
+ "integrity": "sha512-KlSv0pm9kgQSRxXEMgtivPJ4h826YHsuob8pSHcfSZsSXGtvpEAie8S0AnXuObEJ7nhikOb4ahwxDm0H2yW17g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/sade": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
+ "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mri": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
+ "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+ "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.1.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/saxes": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=v12.22.7"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/selderee": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
+ "integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
+ "license": "MIT",
+ "dependencies": {
+ "parseley": "^0.12.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/killymxi"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
+ "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/serve": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.3.tgz",
+ "integrity": "sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@zeit/schemas": "2.36.0",
+ "ajv": "8.12.0",
+ "arg": "5.0.2",
+ "boxen": "7.0.0",
+ "chalk": "5.0.1",
+ "chalk-template": "0.4.0",
+ "clipboardy": "3.0.0",
+ "compression": "1.7.4",
+ "is-port-reachable": "4.0.0",
+ "serve-handler": "6.1.5",
+ "update-check": "1.5.4"
+ },
+ "bin": {
+ "serve": "build/main.js"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/serve-handler": {
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz",
+ "integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.0.0",
+ "content-disposition": "0.5.2",
+ "fast-url-parser": "1.1.3",
+ "mime-types": "2.1.18",
+ "minimatch": "3.1.2",
+ "path-is-inside": "1.0.2",
+ "path-to-regexp": "2.2.1",
+ "range-parser": "1.2.0"
+ }
+ },
+ "node_modules/serve-handler/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/serve-handler/node_modules/content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-handler/node_modules/mime-db": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
+ "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-handler/node_modules/mime-types": {
+ "version": "2.1.18",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
+ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "~1.33.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-handler/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/serve-handler/node_modules/path-to-regexp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz",
+ "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/serve-handler/node_modules/range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/serve/node_modules/chalk": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz",
+ "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/serve/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "license": "ISC"
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
+ "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==",
+ "license": "MIT"
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/shimmer": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
+ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sonner": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.5.0.tgz",
+ "integrity": "sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+ "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true,
+ "license": "CC-BY-3.0"
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.18",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz",
+ "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/spin-delay": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/spin-delay/-/spin-delay-2.0.0.tgz",
+ "integrity": "sha512-uNQnIjJ3Ms5ojVUMJaUZrF2Gs2gsSrVExueYrh8/yGg+ecPj65aZ0QI6ln7dguw9Wpp+bVCqGeY2Q9bT4MCL/A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=17.0.1"
+ }
+ },
+ "node_modules/sql-formatter": {
+ "version": "15.3.1",
+ "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.3.1.tgz",
+ "integrity": "sha512-L/dqan+Hrt0PpPdCbHcI9bdfOvqaQZR7v5c5SWMJ3bUGQSezK09Mm9q2I3B4iObjaq7FyoldIM+fDSmfzGRXCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "get-stdin": "=8.0.0",
+ "nearley": "^2.20.1"
+ },
+ "bin": {
+ "sql-formatter": "bin/sql-formatter-cli.cjs"
+ }
+ },
+ "node_modules/ssri": {
+ "version": "10.0.6",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz",
+ "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/std-env": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz",
+ "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/stdin-discarder": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz",
+ "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/stdin-discarder/node_modules/bl": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
+ "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^6.0.3",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/stdin-discarder/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/stream-shift": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
+ "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/stream-slice": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz",
+ "integrity": "sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==",
+ "license": "MIT"
+ },
+ "node_modules/strict-event-emitter": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz",
+ "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string_decoder/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/string-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
+ "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.11",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz",
+ "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.7",
+ "regexp.prototype.flags": "^1.5.2",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.padend": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz",
+ "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
+ "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
+ "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
+ "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-literal": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz",
+ "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^9.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/strip-literal/node_modules/js-tokens": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz",
+ "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/style-to-object": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz",
+ "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inline-style-parser": "0.1.1"
+ }
+ },
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/sucrase/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/sucrase/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tailwind-merge": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.4.0.tgz",
+ "integrity": "sha512-49AwoOQNKdqKPd9CViyH5wJoSKsCDjUlzL8DxuGp3P1FsGY36NJDAa18jLZcaHAUUuTj+JB8IAo8zWgBNvBF7A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.6",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz",
+ "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.0",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss-animate": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+ "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders"
+ }
+ },
+ "node_modules/tailwindcss-radix": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/tailwindcss-radix/-/tailwindcss-radix-3.0.3.tgz",
+ "integrity": "sha512-uueKWJIY98tU4Fip2FTL2eXBqX428e5HBwbu+8rqqJ9H3NuhkcAGS66wNHZjeix56f6nNBhkhMLpQeIrmVxH/w==",
+ "license": "MIT"
+ },
+ "node_modules/tailwindcss/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/lilconfig": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-fs/node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "license": "ISC"
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
+ "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^10.4.1",
+ "minimatch": "^9.0.4"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/test-exclude/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/test-exclude/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/test-exclude/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/test-exclude/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "license": "MIT",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/thirty-two": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
+ "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
+ "engines": {
+ "node": ">=0.2.6"
+ }
+ },
+ "node_modules/through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "node_modules/through2/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/through2/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/through2/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/tinybench": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz",
+ "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinypool": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz",
+ "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
+ "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tinyspy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.0.tgz",
+ "integrity": "sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/toml": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
+ "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tough-cookie": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
+ "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tough-cookie/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
+ "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "punycode": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/trough": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
+ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz",
+ "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json5": "^2.2.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true,
+ "license": "0BSD"
+ },
+ "node_modules/tsx": {
+ "version": "4.16.2",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz",
+ "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.21.5",
+ "get-tsconfig": "^4.7.5"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/tsx/node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "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"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/turbo-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.2.0.tgz",
+ "integrity": "sha512-FKFg7A0To1VU4CH9YmSMON5QphK0BXjSoiC7D9yMh+mEEbXLUP9qJ4hEt1qcjKtzncs1OpcnjZO8NgrlVbZH+g==",
+ "license": "ISC"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "4.18.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.3.tgz",
+ "integrity": "sha512-Q08/0IrpvM+NMY9PA2rti9Jb+JejTddwmwmVQGskAlhtcrw1wsRzoR6ode6mR+OAabNa75w/dxedSUY2mlphaQ==",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
+ "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
+ "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz",
+ "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
+ "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-/cx37A2S+AOne5uFpD8GzHzV5b/7wncAh4agmIRieAZWXJWbRcue7e8RI6LnpQ7CHy9IHPmALcHcXPXogM6jcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.0.0-alpha.20",
+ "@typescript-eslint/parser": "8.0.0-alpha.20",
+ "@typescript-eslint/utils": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-+Ncj0Q6DT8ZHYNp8h5RndW4Siv52kiPpHEz/i8Sj2rh2y8ZCc5pKSHSslk+eZi0Bdj+/+swNOmDNcL2CrlaEnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-xpU1rMQfnnNZxpHN6YUfr18sGOMcpC9hvt54fupcU6N1qMCagEtkRt1U15x086oJAgAITJGa67454ffAoCxv/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-VQ8Mf8upDCuf0uMTjX/Pdw3gvCZomkG43nuThUuzhK3YFwFmIDTqx0ZWSsYJkVGfll0WrXgIua+rKSP/n6NBWw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/visitor-keys": "8.0.0-alpha.20",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-0aMhjDTvIrkGkHqyM0ZByAwR8BV1f2HhKdYyjtxko8S/Ca4PGjOIjub6VoF+bQwCRxEuV8viNUld78rqm9jqLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.0.0-alpha.20",
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "@typescript-eslint/typescript-estree": "8.0.0-alpha.20"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.0.0-alpha.20",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.0-alpha.20.tgz",
+ "integrity": "sha512-ej06rfct0kalfJgIR8nTR7dF1mgfF83hkylrYas7IAElHfgw4zx99BUGa6VrnHZ1PkxdJBp5PgcO2FmmlOoaRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.0.0-alpha.20",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/typescript-eslint/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/ufo": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz",
+ "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici": {
+ "version": "6.18.2",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.2.tgz",
+ "integrity": "sha512-o/MQLTwRm9IVhOqhZ0NQ9oXax1ygPjw6Vs+Vq/4QRjbOAC3B1GCHy7TYxxbExKlb7bzDRzt9vBWU6BDz0RFfYg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "license": "MIT"
+ },
+ "node_modules/unified": {
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz",
+ "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "bail": "^2.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unique-filename": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+ "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "unique-slug": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+ "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/unist-util-generated": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz",
+ "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz",
+ "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz",
+ "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position-from-estree": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.2.tgz",
+ "integrity": "sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz",
+ "integrity": "sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-visit": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz",
+ "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0",
+ "unist-util-visit-parents": "^5.1.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
+ "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/unplugin": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz",
+ "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.8.1",
+ "chokidar": "^3.5.3",
+ "webpack-sources": "^3.2.3",
+ "webpack-virtual-modules": "^0.5.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
+ "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.1.2",
+ "picocolors": "^1.0.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/update-check": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz",
+ "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "registry-auth-token": "3.3.2",
+ "registry-url": "3.1.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/use-callback-ref": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz",
+ "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sidecar": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
+ "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/util": {
+ "version": "0.12.5",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
+ "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "which-typed-array": "^1.1.2"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/uvu": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz",
+ "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0",
+ "diff": "^5.0.0",
+ "kleur": "^4.0.3",
+ "sade": "^1.7.3"
+ },
+ "bin": {
+ "uvu": "bin.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/uvu/node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/validate-npm-package-name": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz",
+ "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz",
+ "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.39",
+ "rollup": "^4.13.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite-env-only": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/vite-env-only/-/vite-env-only-3.0.3.tgz",
+ "integrity": "sha512-iAb7cTXRrvFShaF1n+G8f6Yqq7sRJcxipNYNQQu0DN5N9P55vJMmLG5lNU5moYGpd+ZH1WhBHdkWi5WjrfImHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.23.7",
+ "@babel/generator": "^7.23.6",
+ "@babel/parser": "^7.23.6",
+ "@babel/traverse": "^7.23.7",
+ "@babel/types": "^7.23.6",
+ "babel-dead-code-elimination": "^1.0.6",
+ "micromatch": "^4.0.5"
+ },
+ "peerDependencies": {
+ "vite": "*"
+ }
+ },
+ "node_modules/vite-node": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz",
+ "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.3.4",
+ "pathe": "^1.1.1",
+ "picocolors": "^1.0.0",
+ "vite": "^5.0.0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite/node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "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"
+ }
+ },
+ "node_modules/vitest": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.3.tgz",
+ "integrity": "sha512-o3HRvU93q6qZK4rI2JrhKyZMMuxg/JRt30E6qeQs6ueaiz5hr1cPj+Sk2kATgQzMMqsa2DiNI0TIK++1ULx8Jw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "@vitest/expect": "2.0.3",
+ "@vitest/pretty-format": "^2.0.3",
+ "@vitest/runner": "2.0.3",
+ "@vitest/snapshot": "2.0.3",
+ "@vitest/spy": "2.0.3",
+ "@vitest/utils": "2.0.3",
+ "chai": "^5.1.1",
+ "debug": "^4.3.5",
+ "execa": "^8.0.1",
+ "magic-string": "^0.30.10",
+ "pathe": "^1.1.2",
+ "std-env": "^3.7.0",
+ "tinybench": "^2.8.0",
+ "tinypool": "^1.0.0",
+ "tinyrainbow": "^1.2.0",
+ "vite": "^5.0.0",
+ "vite-node": "2.0.3",
+ "why-is-node-running": "^2.2.2"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "@vitest/browser": "2.0.3",
+ "@vitest/ui": "2.0.3",
+ "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
+ }
+ }
+ },
+ "node_modules/vitest/node_modules/execa": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
+ "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^8.0.1",
+ "human-signals": "^5.0.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16.17"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/vitest/node_modules/get-stream": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
+ "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vitest/node_modules/human-signals": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
+ "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16.17.0"
+ }
+ },
+ "node_modules/vitest/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vitest/node_modules/magic-string": {
+ "version": "0.30.10",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
+ "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ }
+ },
+ "node_modules/vitest/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vitest/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vitest/node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vitest/node_modules/vite-node": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.3.tgz",
+ "integrity": "sha512-14jzwMx7XTcMB+9BhGQyoEAmSl0eOr3nrnn+Z12WNERtOvLN+d2scbRUvyni05rT3997Bg+rZb47NyP4IQPKXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cac": "^6.7.14",
+ "debug": "^4.3.5",
+ "pathe": "^1.1.2",
+ "tinyrainbow": "^1.2.0",
+ "vite": "^5.0.0"
+ },
+ "bin": {
+ "vite-node": "vite-node.mjs"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/w3c-xmlserializer": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+ "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "xml-name-validator": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/web-encoding": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz",
+ "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==",
+ "license": "MIT",
+ "dependencies": {
+ "util": "^0.12.3"
+ },
+ "optionalDependencies": {
+ "@zxing/text-encoding": "0.9.0"
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack-virtual-modules": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz",
+ "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
+ "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "^5.0.0",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+ "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function.prototype.name": "^1.1.5",
+ "has-tostringtag": "^1.0.0",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.0.5",
+ "is-finalizationregistry": "^1.0.2",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.1.4",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+ "license": "ISC"
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
+ "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/why-is-node-running": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
+ "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz",
+ "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/ws": {
+ "version": "7.5.9",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+ "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-name-validator": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
+ "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yaml": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
+ "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yoctocolors": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.0.2.tgz",
+ "integrity": "sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3fb8573
--- /dev/null
+++ b/package.json
@@ -0,0 +1,171 @@
+{
+ "name": "publicare-ddc2",
+ "private": true,
+ "sideEffects": false,
+ "type": "module",
+ "imports": {
+ "#app/*": "./app/*",
+ "#tests/*": "./tests/*"
+ },
+ "scripts": {
+ "build": "run-s build:*",
+ "build:icons": "tsx ./other/build-icons.ts",
+ "build:remix": "remix-ssg vite:build",
+ "build:server": "tsx ./other/build-server.ts",
+ "predev": "npm run build:icons --silent",
+ "dev": "node ./server/dev-server.js",
+ "prisma:studio": "prisma studio",
+ "format": "prettier --write .",
+ "lint": "eslint .",
+ "setup": "npm run build && prisma generate && prisma migrate deploy && prisma db seed && playwright install",
+ "start": "cross-env NODE_ENV=production node .",
+ "start:mocks": "cross-env NODE_ENV=production MOCKS=true tsx .",
+ "test": "vitest",
+ "coverage": "vitest run --coverage",
+ "test:e2e": "npm run test:e2e:dev --silent",
+ "test:e2e:dev": "playwright test --ui",
+ "pretest:e2e:run": "npm run build",
+ "test:e2e:run": "cross-env CI=true playwright test",
+ "test:e2e:install": "npx playwright install --with-deps chromium",
+ "typecheck": "tsc",
+ "validate": "run-p \"test -- --run\" lint typecheck test:e2e:run"
+ },
+ "prettier": "@epic-web/config/prettier",
+ "eslintIgnore": [
+ "/node_modules",
+ "/build",
+ "/public/build",
+ "/playwright-report",
+ "/server-build"
+ ],
+ "dependencies": {
+ "@conform-to/react": "^1.1.5",
+ "@conform-to/zod": "^1.1.5",
+ "@epic-web/cachified": "^5.2.0",
+ "@epic-web/client-hints": "^1.3.2",
+ "@epic-web/invariant": "^1.0.0",
+ "@epic-web/remember": "^1.1.0",
+ "@epic-web/totp": "^1.1.2",
+ "@nasa-gcn/remix-seo": "^2.0.1",
+ "@paralleldrive/cuid2": "^2.2.2",
+ "@prisma/client": "^5.17.0",
+ "@radix-ui/react-checkbox": "^1.1.1",
+ "@radix-ui/react-dropdown-menu": "^2.1.1",
+ "@radix-ui/react-label": "^2.1.0",
+ "@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-toast": "^1.2.1",
+ "@radix-ui/react-tooltip": "^1.1.2",
+ "@react-email/components": "0.0.21",
+ "@remix-run/express": "2.10.3",
+ "@remix-run/node": "2.10.3",
+ "@remix-run/react": "2.10.3",
+ "@sentry/profiling-node": "^8.18.0",
+ "@sentry/remix": "^8.18.0",
+ "address": "^2.0.3",
+ "bcryptjs": "^2.4.3",
+ "better-sqlite3": "^11.1.2",
+ "chalk": "^5.3.0",
+ "class-variance-authority": "^0.7.0",
+ "close-with-grace": "^1.3.0",
+ "clsx": "^2.1.1",
+ "compression": "^1.7.4",
+ "cookie": "^0.6.0",
+ "cross-env": "^7.0.3",
+ "crypto-js": "^4.2.0",
+ "date-fns": "^3.6.0",
+ "dotenv": "^16.4.5",
+ "execa": "^9.3.0",
+ "express": "^4.19.2",
+ "express-rate-limit": "^7.3.1",
+ "get-port": "^7.1.0",
+ "glob": "^11.0.0",
+ "helmet": "^7.1.0",
+ "input-otp": "^1.2.4",
+ "intl-parse-accept-language": "^1.0.0",
+ "isbot": "^5.1.13",
+ "litefs-js": "^1.1.2",
+ "lru-cache": "^11.0.0",
+ "morgan": "^1.10.0",
+ "prisma": "^5.17.0",
+ "qrcode": "^1.5.3",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "remix-auth": "^3.7.0",
+ "remix-auth-github": "^1.7.0",
+ "remix-utils": "^7.6.0",
+ "set-cookie-parser": "^2.6.0",
+ "sonner": "^1.5.0",
+ "source-map-support": "^0.5.21",
+ "spin-delay": "^2.0.0",
+ "tailwind-merge": "^2.4.0",
+ "tailwindcss": "^3.4.6",
+ "tailwindcss-animate": "^1.0.7",
+ "tailwindcss-radix": "^3.0.3",
+ "vite-env-only": "^3.0.3",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@epic-web/config": "^1.12.0",
+ "@faker-js/faker": "^8.4.1",
+ "@playwright/test": "^1.45.2",
+ "@remix-run/dev": "2.10.3",
+ "@remix-run/testing": "2.10.3",
+ "@sentry/vite-plugin": "^2.21.1",
+ "@sly-cli/sly": "^1.13.0",
+ "@testing-library/dom": "^10.3.2",
+ "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/react": "^16.0.0",
+ "@testing-library/user-event": "^14.5.2",
+ "@total-typescript/ts-reset": "^0.5.1",
+ "@types/bcryptjs": "^2.4.6",
+ "@types/better-sqlite3": "^7.6.11",
+ "@types/compression": "^1.7.5",
+ "@types/cookie": "^0.6.0",
+ "@types/eslint": "^8.56.10",
+ "@types/express": "^4.17.21",
+ "@types/fs-extra": "^11.0.4",
+ "@types/glob": "^8.1.0",
+ "@types/morgan": "^1.9.9",
+ "@types/node": "^20.14.11",
+ "@types/qrcode": "^1.5.5",
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
+ "@types/set-cookie-parser": "^2.4.10",
+ "@types/source-map-support": "^0.5.10",
+ "@vitejs/plugin-react": "^4.3.1",
+ "@vitest/coverage-v8": "^2.0.3",
+ "autoprefixer": "^10.4.19",
+ "enforce-unique": "^1.3.0",
+ "esbuild": "^0.23.0",
+ "eslint": "^9.7.0",
+ "fs-extra": "^11.2.0",
+ "jsdom": "^24.1.0",
+ "msw": "2.3.1",
+ "node-html-parser": "^6.1.13",
+ "npm-run-all": "^4.1.5",
+ "prettier": "^3.3.3",
+ "prettier-plugin-sql": "^0.18.1",
+ "prettier-plugin-tailwindcss": "^0.6.5",
+ "remix-flat-routes": "^0.6.5",
+ "remix-ssg": "^0.0.8",
+ "serve": "^14.2.3",
+ "tsx": "^4.16.2",
+ "typescript": "^5.5.3",
+ "vite": "^5.3.4",
+ "vitest": "^2.0.3"
+ },
+ "engines": {
+ "node": "20"
+ },
+ "epic-stack": {
+ "head": "4dc1f1aeeab221f5edea1898c5476d7ca541d3ae",
+ "date": "2024-10-07T14:40:26Z"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ },
+ "volta": {
+ "node": "20.18.0",
+ "npm": "10.9.0"
+ }
+}
diff --git a/playwright.config.ts b/playwright.config.ts
new file mode 100644
index 0000000..e5d832d
--- /dev/null
+++ b/playwright.config.ts
@@ -0,0 +1,42 @@
+import { defineConfig, devices } from '@playwright/test'
+import 'dotenv/config'
+
+const PORT = process.env.PORT || '3000'
+
+export default defineConfig({
+ testDir: './tests/e2e',
+ timeout: 15 * 1000,
+ expect: {
+ timeout: 5 * 1000,
+ },
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 2 : 0,
+ workers: process.env.CI ? 1 : undefined,
+ reporter: 'html',
+ use: {
+ baseURL: `http://localhost:${PORT}/`,
+ trace: 'on-first-retry',
+ },
+
+ projects: [
+ {
+ name: 'chromium',
+ use: {
+ ...devices['Desktop Chrome'],
+ },
+ },
+ ],
+
+ webServer: {
+ command: process.env.CI ? 'npm run start:mocks' : 'npm run dev',
+ port: Number(PORT),
+ reuseExistingServer: true,
+ stdout: 'pipe',
+ stderr: 'pipe',
+ env: {
+ PORT,
+ NODE_ENV: 'test',
+ },
+ },
+})
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..5ebad51
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,7 @@
+export default {
+ plugins: {
+ 'tailwindcss/nesting': {},
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/prisma/data-b.db b/prisma/data-b.db
new file mode 100644
index 0000000..70d4f02
Binary files /dev/null and b/prisma/data-b.db differ
diff --git a/prisma/migrations/20230914194400_init/migration.sql b/prisma/migrations/20230914194400_init/migration.sql
new file mode 100644
index 0000000..5ee0147
--- /dev/null
+++ b/prisma/migrations/20230914194400_init/migration.sql
@@ -0,0 +1,258 @@
+-- CreateTable
+CREATE TABLE "User" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "email" TEXT NOT NULL,
+ "username" TEXT NOT NULL,
+ "name" TEXT,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL
+);
+
+-- CreateTable
+CREATE TABLE "Note" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "title" TEXT NOT NULL,
+ "content" TEXT NOT NULL,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL,
+ "ownerId" TEXT NOT NULL,
+ CONSTRAINT "Note_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "NoteImage" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "altText" TEXT,
+ "contentType" TEXT NOT NULL,
+ "blob" BLOB NOT NULL,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL,
+ "noteId" TEXT NOT NULL,
+ CONSTRAINT "NoteImage_noteId_fkey" FOREIGN KEY ("noteId") REFERENCES "Note" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "UserImage" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "altText" TEXT,
+ "contentType" TEXT NOT NULL,
+ "blob" BLOB NOT NULL,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL,
+ "userId" TEXT NOT NULL,
+ CONSTRAINT "UserImage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "Password" (
+ "hash" TEXT NOT NULL,
+ "userId" TEXT NOT NULL,
+ CONSTRAINT "Password_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "Session" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "expirationDate" DATETIME NOT NULL,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL,
+ "userId" TEXT NOT NULL,
+ CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "Permission" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "action" TEXT NOT NULL,
+ "entity" TEXT NOT NULL,
+ "access" TEXT NOT NULL,
+ "description" TEXT NOT NULL DEFAULT '',
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL
+);
+
+-- CreateTable
+CREATE TABLE "Role" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "name" TEXT NOT NULL,
+ "description" TEXT NOT NULL DEFAULT '',
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL
+);
+
+-- CreateTable
+CREATE TABLE "Verification" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "type" TEXT NOT NULL,
+ "target" TEXT NOT NULL,
+ "secret" TEXT NOT NULL,
+ "algorithm" TEXT NOT NULL,
+ "digits" INTEGER NOT NULL,
+ "period" INTEGER NOT NULL,
+ "charSet" TEXT NOT NULL,
+ "expiresAt" DATETIME
+);
+
+-- CreateTable
+CREATE TABLE "Connection" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "providerName" TEXT NOT NULL,
+ "providerId" TEXT NOT NULL,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updatedAt" DATETIME NOT NULL,
+ "userId" TEXT NOT NULL,
+ CONSTRAINT "Connection_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "_PermissionToRole" (
+ "A" TEXT NOT NULL,
+ "B" TEXT NOT NULL,
+ CONSTRAINT "_PermissionToRole_A_fkey" FOREIGN KEY ("A") REFERENCES "Permission" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "_PermissionToRole_B_fkey" FOREIGN KEY ("B") REFERENCES "Role" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "_RoleToUser" (
+ "A" TEXT NOT NULL,
+ "B" TEXT NOT NULL,
+ CONSTRAINT "_RoleToUser_A_fkey" FOREIGN KEY ("A") REFERENCES "Role" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT "_RoleToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
+
+-- CreateIndex
+CREATE INDEX "Note_ownerId_idx" ON "Note"("ownerId");
+
+-- CreateIndex
+CREATE INDEX "Note_ownerId_updatedAt_idx" ON "Note"("ownerId", "updatedAt");
+
+-- CreateIndex
+CREATE INDEX "NoteImage_noteId_idx" ON "NoteImage"("noteId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "UserImage_userId_key" ON "UserImage"("userId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Password_userId_key" ON "Password"("userId");
+
+-- CreateIndex
+CREATE INDEX "Session_userId_idx" ON "Session"("userId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Permission_action_entity_access_key" ON "Permission"("action", "entity", "access");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Role_name_key" ON "Role"("name");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Verification_target_type_key" ON "Verification"("target", "type");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Connection_providerName_providerId_key" ON "Connection"("providerName", "providerId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "_PermissionToRole_AB_unique" ON "_PermissionToRole"("A", "B");
+
+-- CreateIndex
+CREATE INDEX "_PermissionToRole_B_index" ON "_PermissionToRole"("B");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "_RoleToUser_AB_unique" ON "_RoleToUser"("A", "B");
+
+-- CreateIndex
+CREATE INDEX "_RoleToUser_B_index" ON "_RoleToUser"("B");
+
+--------------------------------- Manual Seeding --------------------------
+-- Hey there, Kent here! This is how you can reliably seed your database with
+-- some data. You edit the migration.sql file and that will handle it for you.
+
+-- The user Roles and Permissions are seeded here.
+-- If you'd like to customise roles and permissions, you can edit and add the code below to your `prisma/seed.ts` file.
+-- Seed your development database with `npx prisma db seed`
+-- Create a sql dump of your database with `sqlite3 prisma/data.db .dump > seed.sql`
+-- Replace the SQL below with your new Roles & Permissions related SQL from `seed.sql`
+
+-- console.time('đ Created permissions...')
+-- const entities = ['user', 'note']
+-- const actions = ['create', 'read', 'update', 'delete']
+-- const accesses = ['own', 'any'] as const
+
+-- let permissionsToCreate = []
+-- for (const entity of entities) {
+-- for (const action of actions) {
+-- for (const access of accesses) {
+-- permissionsToCreate.push({ entity, action, access })
+-- }
+-- }
+-- }
+-- await prisma.permission.createMany({ data: permissionsToCreate })
+-- console.timeEnd('đ Created permissions...')
+
+-- console.time('đ Created roles...')
+-- await prisma.role.create({
+-- data: {
+-- name: 'admin',
+-- permissions: {
+-- connect: await prisma.permission.findMany({
+-- select: { id: true },
+-- where: { access: 'any' },
+-- }),
+-- },
+-- },
+-- })
+-- await prisma.role.create({
+-- data: {
+-- name: 'user',
+-- permissions: {
+-- connect: await prisma.permission.findMany({
+-- select: { id: true },
+-- where: { access: 'own' },
+-- }),
+-- },
+-- },
+-- })
+-- console.timeEnd('đ Created roles...')
+
+INSERT INTO Permission VALUES('clnf2zvli0000pcou3zzzzome','create','user','own','',1696625465526,1696625465526);
+INSERT INTO Permission VALUES('clnf2zvll0001pcouly1310ku','create','user','any','',1696625465529,1696625465529);
+INSERT INTO Permission VALUES('clnf2zvll0002pcouka7348re','read','user','own','',1696625465530,1696625465530);
+INSERT INTO Permission VALUES('clnf2zvlm0003pcouea4dee51','read','user','any','',1696625465530,1696625465530);
+INSERT INTO Permission VALUES('clnf2zvlm0004pcou2guvolx5','update','user','own','',1696625465531,1696625465531);
+INSERT INTO Permission VALUES('clnf2zvln0005pcoun78ps5ap','update','user','any','',1696625465531,1696625465531);
+INSERT INTO Permission VALUES('clnf2zvlo0006pcouyoptc5jp','delete','user','own','',1696625465532,1696625465532);
+INSERT INTO Permission VALUES('clnf2zvlo0007pcouw1yzoyam','delete','user','any','',1696625465533,1696625465533);
+INSERT INTO Permission VALUES('clnf2zvlp0008pcou9r0fhbm8','create','note','own','',1696625465533,1696625465533);
+INSERT INTO Permission VALUES('clnf2zvlp0009pcouj3qib9q9','create','note','any','',1696625465534,1696625465534);
+INSERT INTO Permission VALUES('clnf2zvlq000apcouxnspejs9','read','note','own','',1696625465535,1696625465535);
+INSERT INTO Permission VALUES('clnf2zvlr000bpcouf4cg3x72','read','note','any','',1696625465535,1696625465535);
+INSERT INTO Permission VALUES('clnf2zvlr000cpcouy1vp6oeg','update','note','own','',1696625465536,1696625465536);
+INSERT INTO Permission VALUES('clnf2zvls000dpcouvzwjjzrq','update','note','any','',1696625465536,1696625465536);
+INSERT INTO Permission VALUES('clnf2zvls000epcou4ts5ui8f','delete','note','own','',1696625465537,1696625465537);
+INSERT INTO Permission VALUES('clnf2zvlt000fpcouk29jbmxn','delete','note','any','',1696625465538,1696625465538);
+
+INSERT INTO Role VALUES('clnf2zvlw000gpcour6dyyuh6','admin','',1696625465540,1696625465540);
+INSERT INTO Role VALUES('clnf2zvlx000hpcou5dfrbegs','user','',1696625465542,1696625465542);
+
+INSERT INTO _PermissionToRole VALUES('clnf2zvll0001pcouly1310ku','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlm0003pcouea4dee51','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvln0005pcoun78ps5ap','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlo0007pcouw1yzoyam','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlp0009pcouj3qib9q9','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlr000bpcouf4cg3x72','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvls000dpcouvzwjjzrq','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlt000fpcouk29jbmxn','clnf2zvlw000gpcour6dyyuh6');
+INSERT INTO _PermissionToRole VALUES('clnf2zvli0000pcou3zzzzome','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvll0002pcouka7348re','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlm0004pcou2guvolx5','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlo0006pcouyoptc5jp','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlp0008pcou9r0fhbm8','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlq000apcouxnspejs9','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvlr000cpcouy1vp6oeg','clnf2zvlx000hpcou5dfrbegs');
+INSERT INTO _PermissionToRole VALUES('clnf2zvls000epcou4ts5ui8f','clnf2zvlx000hpcou5dfrbegs');
diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml
new file mode 100644
index 0000000..e5e5c47
--- /dev/null
+++ b/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "sqlite"
\ No newline at end of file
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000..975d243
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,169 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "sqlite"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id String @id @default(cuid())
+ email String @unique
+ username String @unique
+ name String?
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ image UserImage?
+ password Password?
+ notes Note[]
+ roles Role[]
+ sessions Session[]
+ connections Connection[]
+}
+
+model Note {
+ id String @id @default(cuid())
+ title String
+ content String
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ ownerId String
+
+ images NoteImage[]
+
+ // non-unique foreign key
+ @@index([ownerId])
+ // This helps our order by in the user search a LOT
+ @@index([ownerId, updatedAt])
+}
+
+model NoteImage {
+ id String @id @default(cuid())
+ altText String?
+ contentType String
+ blob Bytes
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ note Note @relation(fields: [noteId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ noteId String
+
+ // non-unique foreign key
+ @@index([noteId])
+}
+
+model UserImage {
+ id String @id @default(cuid())
+ altText String?
+ contentType String
+ blob Bytes
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ userId String @unique
+}
+
+model Password {
+ hash String
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ userId String @unique
+}
+
+model Session {
+ id String @id @default(cuid())
+ expirationDate DateTime
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ userId String
+
+ // non-unique foreign key
+ @@index([userId])
+}
+
+model Permission {
+ id String @id @default(cuid())
+ action String // e.g. create, read, update, delete
+ entity String // e.g. note, user, etc.
+ access String // e.g. own or any
+ description String @default("")
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ roles Role[]
+
+ @@unique([action, entity, access])
+}
+
+model Role {
+ id String @id @default(cuid())
+ name String @unique
+ description String @default("")
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ users User[]
+ permissions Permission[]
+}
+
+model Verification {
+ id String @id @default(cuid())
+ createdAt DateTime @default(now())
+
+ /// The type of verification, e.g. "email" or "phone"
+ type String
+
+ /// The thing we're trying to verify, e.g. a user's email or phone number
+ target String
+
+ /// The secret key used to generate the otp
+ secret String
+
+ /// The algorithm used to generate the otp
+ algorithm String
+
+ /// The number of digits in the otp
+ digits Int
+
+ /// The number of seconds the otp is valid for
+ period Int
+
+ /// The valid characters for the otp
+ charSet String
+
+ /// When it's safe to delete this verification
+ expiresAt DateTime?
+
+ @@unique([target, type])
+}
+
+model Connection {
+ id String @id @default(cuid())
+ providerName String
+ providerId String
+
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade)
+ userId String
+
+ @@unique([providerName, providerId])
+}
diff --git a/prisma/seed.ts b/prisma/seed.ts
new file mode 100644
index 0000000..f38edef
--- /dev/null
+++ b/prisma/seed.ts
@@ -0,0 +1,235 @@
+import { faker } from '@faker-js/faker'
+import { promiseHash } from 'remix-utils/promise'
+import { prisma } from '#app/utils/db.server.ts'
+import { MOCK_CODE_GITHUB } from '#app/utils/providers/constants'
+import {
+ cleanupDb,
+ createPassword,
+ createUser,
+ getNoteImages,
+ getUserImages,
+ img,
+} from '#tests/db-utils.ts'
+import { insertGitHubUser } from '#tests/mocks/github.ts'
+
+async function seed() {
+ console.log('đą Seeding...')
+ console.time(`đą Database has been seeded`)
+
+ console.time('𧚠Cleaned up the database...')
+ await cleanupDb()
+ console.timeEnd('𧚠Cleaned up the database...')
+
+ const totalUsers = 5
+ console.time(`đ¤ Created ${totalUsers} users...`)
+ const noteImages = await getNoteImages()
+ const userImages = await getUserImages()
+
+ for (let index = 0; index < totalUsers; index++) {
+ const userData = createUser()
+ await prisma.user
+ .create({
+ select: { id: true },
+ data: {
+ ...userData,
+ password: { create: createPassword(userData.username) },
+ image: { create: userImages[index % userImages.length] },
+ roles: { connect: { name: 'user' } },
+ notes: {
+ create: Array.from({
+ length: faker.number.int({ min: 1, max: 3 }),
+ }).map(() => ({
+ title: faker.lorem.sentence(),
+ content: faker.lorem.paragraphs(),
+ images: {
+ create: Array.from({
+ length: faker.number.int({ min: 1, max: 3 }),
+ }).map(() => {
+ const imgNumber = faker.number.int({ min: 0, max: 9 })
+ const img = noteImages[imgNumber]
+ if (!img) {
+ throw new Error(`Could not find image #${imgNumber}`)
+ }
+ return img
+ }),
+ },
+ })),
+ },
+ },
+ })
+ .catch((e) => {
+ console.error('Error creating a user:', e)
+ return null
+ })
+ }
+ console.timeEnd(`đ¤ Created ${totalUsers} users...`)
+
+ console.time(`đ¨ Created admin user "kody"`)
+
+ const kodyImages = await promiseHash({
+ kodyUser: img({ filepath: './tests/fixtures/images/user/kody.png' }),
+ cuteKoala: img({
+ altText: 'an adorable koala cartoon illustration',
+ filepath: './tests/fixtures/images/kody-notes/cute-koala.png',
+ }),
+ koalaEating: img({
+ altText: 'a cartoon illustration of a koala in a tree eating',
+ filepath: './tests/fixtures/images/kody-notes/koala-eating.png',
+ }),
+ koalaCuddle: img({
+ altText: 'a cartoon illustration of koalas cuddling',
+ filepath: './tests/fixtures/images/kody-notes/koala-cuddle.png',
+ }),
+ mountain: img({
+ altText: 'a beautiful mountain covered in snow',
+ filepath: './tests/fixtures/images/kody-notes/mountain.png',
+ }),
+ koalaCoder: img({
+ altText: 'a koala coding at the computer',
+ filepath: './tests/fixtures/images/kody-notes/koala-coder.png',
+ }),
+ koalaMentor: img({
+ altText:
+ 'a koala in a friendly and helpful posture. The Koala is standing next to and teaching a woman who is coding on a computer and shows positive signs of learning and understanding what is being explained.',
+ filepath: './tests/fixtures/images/kody-notes/koala-mentor.png',
+ }),
+ koalaSoccer: img({
+ altText: 'a cute cartoon koala kicking a soccer ball on a soccer field ',
+ filepath: './tests/fixtures/images/kody-notes/koala-soccer.png',
+ }),
+ })
+
+ const githubUser = await insertGitHubUser(MOCK_CODE_GITHUB)
+
+ await prisma.user.create({
+ select: { id: true },
+ data: {
+ email: 'kody@kcd.dev',
+ username: 'kody',
+ name: 'Kody',
+ image: { create: kodyImages.kodyUser },
+ password: { create: createPassword('kodylovesyou') },
+ connections: {
+ create: { providerName: 'github', providerId: githubUser.profile.id },
+ },
+ roles: { connect: [{ name: 'admin' }, { name: 'user' }] },
+ notes: {
+ create: [
+ {
+ id: 'd27a197e',
+ title: 'Basic Koala Facts',
+ content:
+ 'Koalas are found in the eucalyptus forests of eastern Australia. They have grey fur with a cream-coloured chest, and strong, clawed feet, perfect for living in the branches of trees!',
+ images: { create: [kodyImages.cuteKoala, kodyImages.koalaEating] },
+ },
+ {
+ id: '414f0c09',
+ title: 'Koalas like to cuddle',
+ content:
+ 'Cuddly critters, koalas measure about 60cm to 85cm long, and weigh about 14kg.',
+ images: {
+ create: [kodyImages.koalaCuddle],
+ },
+ },
+ {
+ id: '260366b1',
+ title: 'Not bears',
+ content:
+ "Although you may have heard people call them koala 'bears', these awesome animals arenât bears at all â they are in fact marsupials. A group of mammals, most marsupials have pouches where their newborns develop.",
+ },
+ {
+ id: 'bb79cf45',
+ title: 'Snowboarding Adventure',
+ content:
+ "Today was an epic day on the slopes! Shredded fresh powder with my friends, caught some sick air, and even attempted a backflip. Can't wait for the next snowy adventure!",
+ images: {
+ create: [kodyImages.mountain],
+ },
+ },
+ {
+ id: '9f4308be',
+ title: 'Onewheel Tricks',
+ content:
+ "Mastered a new trick on my Onewheel today called '180 Spin'. It's exhilarating to carve through the streets while pulling off these rad moves. Time to level up and learn more!",
+ },
+ {
+ id: '306021fb',
+ title: 'Coding Dilemma',
+ content:
+ "Stuck on a bug in my latest coding project. Need to figure out why my function isn't returning the expected output. Time to dig deep, debug, and conquer this challenge!",
+ images: {
+ create: [kodyImages.koalaCoder],
+ },
+ },
+ {
+ id: '16d4912a',
+ title: 'Coding Mentorship',
+ content:
+ "Had a fantastic coding mentoring session today with Sarah. Helped her understand the concept of recursion, and she made great progress. It's incredibly fulfilling to help others improve their coding skills.",
+ images: {
+ create: [kodyImages.koalaMentor],
+ },
+ },
+ {
+ id: '3199199e',
+ title: 'Koala Fun Facts',
+ content:
+ "Did you know that koalas sleep for up to 20 hours a day? It's because their diet of eucalyptus leaves doesn't provide much energy. But when I'm awake, I enjoy munching on leaves, chilling in trees, and being the cuddliest koala around!",
+ },
+ {
+ id: '2030ffd3',
+ title: 'Skiing Adventure',
+ content:
+ 'Spent the day hitting the slopes on my skis. The fresh powder made for some incredible runs and breathtaking views. Skiing down the mountain at top speed is an adrenaline rush like no other!',
+ images: {
+ create: [kodyImages.mountain],
+ },
+ },
+ {
+ id: 'f375a804',
+ title: 'Code Jam Success',
+ content:
+ 'Participated in a coding competition today and secured the first place! The adrenaline, the challenging problems, and the satisfaction of finding optimal solutionsâit was an amazing experience. Feeling proud and motivated to keep pushing my coding skills further!',
+ images: {
+ create: [kodyImages.koalaCoder],
+ },
+ },
+ {
+ id: '562c541b',
+ title: 'Koala Conservation Efforts',
+ content:
+ "Joined a local conservation group to protect koalas and their habitats. Together, we're planting more eucalyptus trees, raising awareness about their endangered status, and working towards a sustainable future for these adorable creatures. Every small step counts!",
+ },
+ // extra long note to test scrolling
+ {
+ id: 'f67ca40b',
+ title: 'Game day',
+ content:
+ "Just got back from the most amazing game. I've been playing soccer for a long time, but I've not once scored a goal. Well, today all that changed! I finally scored my first ever goal.\n\nI'm in an indoor league, and my team's not the best, but we're pretty good and I have fun, that's all that really matters. Anyway, I found myself at the other end of the field with the ball. It was just me and the goalie. I normally just kick the ball and hope it goes in, but the ball was already rolling toward the goal. The goalie was about to get the ball, so I had to charge. I managed to get possession of the ball just before the goalie got it. I brought it around the goalie and had a perfect shot. I screamed so loud in excitement. After all these years playing, I finally scored a goal!\n\nI know it's not a lot for most folks, but it meant a lot to me. We did end up winning the game by one. It makes me feel great that I had a part to play in that.\n\nIn this team, I'm the captain. I'm constantly cheering my team on. Even after getting injured, I continued to come and watch from the side-lines. I enjoy yelling (encouragingly) at my team mates and helping them be the best they can. I'm definitely not the best player by a long stretch. But I really enjoy the game. It's a great way to get exercise and have good social interactions once a week.\n\nThat said, it can be hard to keep people coming and paying dues and stuff. If people don't show up it can be really hard to find subs. I have a list of people I can text, but sometimes I can't find anyone.\n\nBut yeah, today was awesome. I felt like more than just a player that gets in the way of the opposition, but an actual asset to the team. Really great feeling.\n\nAnyway, I'm rambling at this point and really this is just so we can have a note that's pretty long to test things out. I think it's long enough now... Cheers!",
+ images: {
+ create: [kodyImages.koalaSoccer],
+ },
+ },
+ ],
+ },
+ },
+ })
+ console.timeEnd(`đ¨ Created admin user "kody"`)
+
+ console.timeEnd(`đą Database has been seeded`)
+}
+
+seed()
+ .catch((e) => {
+ console.error(e)
+ process.exit(1)
+ })
+ .finally(async () => {
+ await prisma.$disconnect()
+ })
+
+// we're ok to import from the test directory in this file
+/*
+eslint
+ no-restricted-imports: "off",
+*/
diff --git a/public/demodata/Verordnung_muster.webp b/public/demodata/Verordnung_muster.webp
new file mode 100644
index 0000000..66f9a16
Binary files /dev/null and b/public/demodata/Verordnung_muster.webp differ
diff --git a/public/demodata/e-rezept.png b/public/demodata/e-rezept.png
new file mode 100644
index 0000000..cc32597
Binary files /dev/null and b/public/demodata/e-rezept.png differ
diff --git a/public/demodata/prescription.pdf b/public/demodata/prescription.pdf
new file mode 100644
index 0000000..a151181
Binary files /dev/null and b/public/demodata/prescription.pdf differ
diff --git a/public/demodata/rezept.png b/public/demodata/rezept.png
new file mode 100644
index 0000000..4efcae2
Binary files /dev/null and b/public/demodata/rezept.png differ
diff --git a/public/demodata/verordnung.jpg b/public/demodata/verordnung.jpg
new file mode 100644
index 0000000..27c53b5
Binary files /dev/null and b/public/demodata/verordnung.jpg differ
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..01deac7
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/favicons/README.md b/public/favicons/README.md
new file mode 100644
index 0000000..e28c8f4
--- /dev/null
+++ b/public/favicons/README.md
@@ -0,0 +1,12 @@
+# Favicon
+
+This directory has the icons used for android devices. In some cases, we cannot
+reliably detect light/dark mode preference. Hence these icons should not have a
+transparent background. These icons are referenced in the `site.webmanifest`
+file.
+
+The icons used by modern browsers and Apple devices are in `app/assets/favicons`
+as they can be imported with a fingerprint to bust the browser cache.
+
+Note, there's also a `favicon.ico` in the root of `/public` which some older
+browsers will request automatically. This is a fallback for those browsers.
diff --git a/public/favicons/android-chrome-192x192.png b/public/favicons/android-chrome-192x192.png
new file mode 100644
index 0000000..f24aaa2
Binary files /dev/null and b/public/favicons/android-chrome-192x192.png differ
diff --git a/public/favicons/android-chrome-512x512.png b/public/favicons/android-chrome-512x512.png
new file mode 100644
index 0000000..67125b8
Binary files /dev/null and b/public/favicons/android-chrome-512x512.png differ
diff --git a/public/img/user.png b/public/img/user.png
new file mode 100644
index 0000000..683fcee
Binary files /dev/null and b/public/img/user.png differ
diff --git a/public/site.webmanifest b/public/site.webmanifest
new file mode 100644
index 0000000..1bf9260
--- /dev/null
+++ b/public/site.webmanifest
@@ -0,0 +1,20 @@
+{
+ "name": "Epic Notes",
+ "short_name": "Epic Notes",
+ "start_url": "/",
+ "icons": [
+ {
+ "src": "/favicons/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/favicons/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#A9ADC1",
+ "background_color": "#1f2028",
+ "display": "standalone"
+}
diff --git a/remix.init/gitignore b/remix.init/gitignore
new file mode 100644
index 0000000..320b1c0
--- /dev/null
+++ b/remix.init/gitignore
@@ -0,0 +1,26 @@
+node_modules
+.DS_store
+
+/build
+/public/build
+/server-build
+.env
+.cache
+
+/prisma/data.db
+/prisma/data.db-journal
+/tests/prisma
+
+/test-results/
+/playwright-report/
+/playwright/.cache/
+/tests/fixtures/email/
+/coverage
+
+/other/cache.db
+
+# Easy way to create temporary files/folders that won't accidentally be added to git
+*.local.*
+
+# generated files
+/app/components/ui/icons
diff --git a/remix.init/index.js b/remix.init/index.js
new file mode 100644
index 0000000..e5e36c0
--- /dev/null
+++ b/remix.init/index.js
@@ -0,0 +1,4 @@
+module.exports = async (...args) => {
+ const { default: main } = await import('./index.mjs')
+ await main(...args)
+}
diff --git a/remix.init/index.mjs b/remix.init/index.mjs
new file mode 100644
index 0000000..2867c16
--- /dev/null
+++ b/remix.init/index.mjs
@@ -0,0 +1,315 @@
+import { execSync } from 'node:child_process'
+import crypto from 'node:crypto'
+import fs from 'node:fs/promises'
+import path from 'node:path'
+import toml from '@iarna/toml'
+import { $ } from 'execa'
+import inquirer from 'inquirer'
+import open from 'open'
+import parseGitHubURL from 'parse-github-url'
+
+const escapeRegExp = (string) =>
+ // $& means the whole matched string
+ string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+
+const getRandomString = (length) => crypto.randomBytes(length).toString('hex')
+const getRandomString32 = () => getRandomString(32)
+
+export default async function main({ rootDirectory }) {
+ const FLY_TOML_PATH = path.join(rootDirectory, 'fly.toml')
+ const EXAMPLE_ENV_PATH = path.join(rootDirectory, '.env.example')
+ const ENV_PATH = path.join(rootDirectory, '.env')
+ const PKG_PATH = path.join(rootDirectory, 'package.json')
+
+ const appNameRegex = escapeRegExp('epic-stack-template')
+
+ const DIR_NAME = path.basename(rootDirectory)
+ const SUFFIX = getRandomString(2)
+
+ const APP_NAME = (DIR_NAME + '-' + SUFFIX)
+ // get rid of anything that's not allowed in an app name
+ .replace(/[^a-zA-Z0-9-_]/g, '-')
+ .toLowerCase()
+
+ const [flyTomlContent, env, packageJsonString] = await Promise.all([
+ fs.readFile(FLY_TOML_PATH, 'utf-8'),
+ fs.readFile(EXAMPLE_ENV_PATH, 'utf-8'),
+ fs.readFile(PKG_PATH, 'utf-8'),
+ ])
+
+ const newEnv = env.replace(
+ /^SESSION_SECRET=.*$/m,
+ `SESSION_SECRET="${getRandomString(16)}"`,
+ )
+
+ const newFlyTomlContent = flyTomlContent.replace(
+ new RegExp(appNameRegex, 'g'),
+ APP_NAME,
+ )
+
+ const packageJson = JSON.parse(packageJsonString)
+
+ packageJson.name = APP_NAME
+ delete packageJson.author
+ delete packageJson.license
+
+ const fileOperationPromises = [
+ fs.writeFile(FLY_TOML_PATH, newFlyTomlContent),
+ fs.writeFile(ENV_PATH, newEnv),
+ fs.writeFile(PKG_PATH, JSON.stringify(packageJson, null, 2)),
+ fs.copyFile(
+ path.join(rootDirectory, 'remix.init', 'gitignore'),
+ path.join(rootDirectory, '.gitignore'),
+ ),
+ fs.rm(path.join(rootDirectory, 'LICENSE.md')),
+ fs.rm(path.join(rootDirectory, 'CONTRIBUTING.md')),
+ fs.rm(path.join(rootDirectory, 'docs'), { recursive: true }),
+ fs.rm(path.join(rootDirectory, 'tests/e2e/notes.test.ts')),
+ fs.rm(path.join(rootDirectory, 'tests/e2e/search.test.ts')),
+ fs.rm(path.join(rootDirectory, '.github/workflows/version.yml')),
+ ]
+
+ await Promise.all(fileOperationPromises)
+
+ if (!process.env.SKIP_SETUP) {
+ execSync('npm run setup', { cwd: rootDirectory, stdio: 'inherit' })
+ }
+
+ if (!process.env.SKIP_FORMAT) {
+ execSync('npm run format -- --log-level warn', {
+ cwd: rootDirectory,
+ stdio: 'inherit',
+ })
+ }
+
+ if (!process.env.SKIP_DEPLOYMENT) {
+ await setupDeployment({ rootDirectory }).catch((error) => {
+ console.error(error)
+
+ console.error(
+ `Looks like something went wrong setting up deployment. Sorry about that. Check the docs for instructions on how to get deployment setup yourself (https://github.com/epicweb-dev/epic-stack/blob/main/docs/deployment.md).`,
+ )
+ })
+ }
+
+ console.log(
+ `
+Setup is complete. You're now ready to rock and roll đ¨
+
+What's next?
+
+- Start development with \`npm run dev\`
+- Run tests with \`npm run test\` and \`npm run test:e2e\`
+ `.trim(),
+ )
+}
+
+async function setupDeployment({ rootDirectory }) {
+ const $I = $({ stdio: 'inherit', cwd: rootDirectory })
+
+ const { shouldSetupDeployment } = await inquirer.prompt([
+ {
+ name: 'shouldSetupDeployment',
+ type: 'confirm',
+ default: true,
+ message: 'Would you like to set up deployment right now?',
+ },
+ ])
+
+ if (!shouldSetupDeployment) {
+ console.log(
+ `Ok, check the docs (https://github.com/epicweb-dev/epic-stack/blob/main/docs/deployment.md) when you're ready to set that up.`,
+ )
+ return
+ }
+
+ const hasFly = await $`fly version`.then(
+ () => true,
+ () => false,
+ )
+ if (!hasFly) {
+ console.log(
+ `You need to install Fly first. Follow the instructions here: https://fly.io/docs/hands-on/install-flyctl/`,
+ )
+ return
+ }
+ const loggedInUser = await ensureLoggedIn()
+ if (!loggedInUser) {
+ console.log(
+ `Ok, check the docs when you're ready to get this deployed: https://github.com/epicweb-dev/epic-stack/blob/main/docs/deployment.md`,
+ )
+ }
+
+ console.log('đ Determining the best region for you...')
+ const primaryRegion = await getPreferredRegion()
+
+ const flyConfig = toml.parse(
+ await fs.readFile(path.join(rootDirectory, 'fly.toml')),
+ )
+ flyConfig.primary_region = primaryRegion
+ await fs.writeFile(
+ path.join(rootDirectory, 'fly.toml'),
+ toml.stringify(flyConfig),
+ )
+
+ const { app: APP_NAME } = flyConfig
+
+ console.log(`𼪠Creating app ${APP_NAME} and ${APP_NAME}-staging...`)
+ await $I`fly apps create ${APP_NAME}-staging`
+ await $I`fly apps create ${APP_NAME}`
+
+ console.log(`𤍠Setting secrets in apps`)
+ await $I`fly secrets set SESSION_SECRET=${getRandomString32()} INTERNAL_COMMAND_TOKEN=${getRandomString32()} HONEYPOT_SECRET=${getRandomString32()} ALLOW_INDEXING=false --app ${APP_NAME}-staging`
+ await $I`fly secrets set SESSION_SECRET=${getRandomString32()} INTERNAL_COMMAND_TOKEN=${getRandomString32()} HONEYPOT_SECRET=${getRandomString32()} --app ${APP_NAME}`
+
+ console.log(
+ `đ Creating volumes. Answer "yes" when it warns you about downtime. You can add more volumes later (when you actually start getting paying customers ďż˝).`,
+ )
+ await $I`fly volumes create data --region ${primaryRegion} --size 1 --app ${APP_NAME}-staging`
+ await $I`fly volumes create data --region ${primaryRegion} --size 1 --app ${APP_NAME}`
+
+ // attach consul
+ console.log(`đ Attaching consul`)
+ await $I`fly consul attach --app ${APP_NAME}-staging`
+ await $I`fly consul attach --app ${APP_NAME}`
+
+ const { shouldDeploy } = await inquirer.prompt([
+ {
+ name: 'shouldDeploy',
+ type: 'confirm',
+ default: true,
+ message:
+ 'Would you like to deploy right now? (This will take a while, and you can always wait until you push to GitHub instead).',
+ },
+ ])
+ if (shouldDeploy) {
+ console.log(`đ Deploying apps...`)
+ console.log(` Starting with staging`)
+ await $I`fly deploy --app ${APP_NAME}-staging`
+ await open(`https://${APP_NAME}-staging.fly.dev/`)
+
+ console.log(` Staging deployed... Deploying production...`)
+ await $I`fly deploy --app ${APP_NAME}`
+ await open(`https://${APP_NAME}.fly.dev/`)
+ console.log(` Production deployed...`)
+ }
+
+ const { shouldSetupGitHub } = await inquirer.prompt([
+ {
+ name: 'shouldSetupGitHub',
+ type: 'confirm',
+ default: true,
+ message: 'Would you like to setup GitHub Action deployment right now?',
+ },
+ ])
+ if (shouldSetupGitHub) {
+ console.log(`â Initializing git repo...`)
+ // it's possible there's already a git repo initialized so we'll just ignore
+ // any errors and hope things work out.
+ await $I`git init`.catch(() => {})
+
+ console.log(
+ `Opening repo.new. Please create a new repo and paste the URL below.`,
+ )
+ await open(`https://repo.new`)
+
+ const { repoURL } = await inquirer.prompt([
+ {
+ name: 'repoURL',
+ type: 'input',
+ message: 'What is the URL of your repo?',
+ },
+ ])
+
+ const githubParts = parseGitHubURL(repoURL)
+
+ if (!githubParts) {
+ throw new Error(`Invalid GitHub URL: ${repoURL}`)
+ }
+
+ console.log(
+ `Opening Fly Tokens Dashboard and GitHub Action Secrets pages. Please create a new token on Fly and set it as the value for a new secret called FLY_API_TOKEN on GitHub.`,
+ )
+ await open(`https://web.fly.io/user/personal_access_tokens/new`)
+ await open(`${repoURL}/settings/secrets/actions/new`)
+
+ console.log(
+ `Once you're finished with setting the token, you should be good to add the remote, commit, and push!`,
+ )
+ }
+ console.log('All done đ Happy building')
+}
+
+async function ensureLoggedIn() {
+ const loggedInUser = await $`fly auth whoami`.then(
+ ({ stdout }) => stdout,
+ () => null,
+ )
+ if (loggedInUser) {
+ const answers = await inquirer.prompt([
+ {
+ name: 'proceed',
+ type: 'list',
+ default: 'Yes',
+ message: `You're logged in as ${loggedInUser}. Proceed?`,
+ choices: ['Yes', 'Login as another user', 'Exit'],
+ },
+ ])
+ switch (answers.proceed) {
+ case 'Yes': {
+ return loggedInUser
+ }
+ case 'Login as another user': {
+ await $`fly auth logout`
+ return ensureLoggedIn()
+ }
+ default: {
+ return null
+ }
+ }
+ } else {
+ console.log(`You need to login to Fly first. Running \`fly auth login\`...`)
+ await $({ stdio: 'inherit' })`fly auth login`
+ return ensureLoggedIn()
+ }
+}
+
+async function getPreferredRegion() {
+ const {
+ platform: { requestRegion: defaultRegion },
+ } = await makeFlyRequest({ query: 'query {platform {requestRegion}}' })
+
+ const availableRegions = await makeFlyRequest({
+ query: `{platform {regions {name code}}}`,
+ })
+ const { preferredRegion } = await inquirer.prompt([
+ {
+ name: 'preferredRegion',
+ type: 'list',
+ default: defaultRegion,
+ message: `Which region would you like to deploy to? The closest to you is ${defaultRegion}.`,
+ choices: availableRegions.platform.regions.map((region) => ({
+ name: `${region.name} (${region.code})`,
+ value: region.code,
+ })),
+ },
+ ])
+ return preferredRegion
+}
+
+let flyToken = null
+async function makeFlyRequest({ query, variables }) {
+ if (!flyToken) {
+ flyToken = (await $`fly auth token`).stdout.trim()
+ }
+
+ const json = await fetch('https://api.fly.io/graphql', {
+ method: 'POST',
+ body: JSON.stringify({ query, variables }),
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${flyToken}`,
+ },
+ }).then((response) => response.json())
+ return json.data
+}
diff --git a/remix.init/package-lock.json b/remix.init/package-lock.json
new file mode 100644
index 0000000..d3755cc
--- /dev/null
+++ b/remix.init/package-lock.json
@@ -0,0 +1,1731 @@
+{
+ "name": "remix.init",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "remix.init",
+ "dependencies": {
+ "@iarna/toml": "^2.2.5",
+ "execa": "^7.1.1",
+ "inquirer": "^9.2.6",
+ "open": "^9.1.0",
+ "parse-github-url": "^1.0.2"
+ }
+ },
+ "node_modules/@iarna/toml": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
+ "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "dependencies": {
+ "big-integer": "^1.6.44"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "dependencies": {
+ "run-applescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
+ "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz",
+ "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz",
+ "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "dependencies": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
+ "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
+ "dependencies": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/execa": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz",
+ "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execa/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/execa/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/figures": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz",
+ "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==",
+ "dependencies": {
+ "escape-string-regexp": "^5.0.0",
+ "is-unicode-supported": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/inquirer": {
+ "version": "9.2.6",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.6.tgz",
+ "integrity": "sha512-y71l237eJJKS4rl7sQcEUiMhrR0pB/ZnRMMTxLpjJhWL4hdWCT03a6jJnC1w6qIPSRZWEozuieGt3v7XaEJYFw==",
+ "dependencies": {
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^5.2.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^4.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^5.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "1.0.0",
+ "ora": "^5.4.1",
+ "run-async": "^3.0.0",
+ "rxjs": "^7.8.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "through": "^2.3.6",
+ "wrap-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+ "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-wsl/node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "dependencies": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ora/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/ora/node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
+ "bin": {
+ "parse-github-url": "cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/run-applescript/node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/run-applescript/node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-applescript/node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/run-applescript/node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
+ "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+ },
+ "node_modules/titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA=="
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ }
+ },
+ "dependencies": {
+ "@iarna/toml": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
+ "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
+ },
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "requires": {
+ "type-fest": "^0.21.3"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
+ "big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg=="
+ },
+ "bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "requires": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "requires": {
+ "big-integer": "^1.6.44"
+ }
+ },
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "requires": {
+ "run-applescript": "^5.0.0"
+ }
+ },
+ "chalk": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
+ "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA=="
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz",
+ "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g=="
+ },
+ "cli-width": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.0.0.tgz",
+ "integrity": "sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw=="
+ },
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "requires": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ }
+ },
+ "default-browser-id": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
+ "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
+ "requires": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ }
+ },
+ "defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "requires": {
+ "clone": "^1.0.2"
+ }
+ },
+ "define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "escape-string-regexp": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+ "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="
+ },
+ "execa": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz",
+ "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==",
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "dependencies": {
+ "mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="
+ },
+ "onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "requires": {
+ "mimic-fn": "^4.0.0"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "figures": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz",
+ "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==",
+ "requires": {
+ "escape-string-regexp": "^5.0.0",
+ "is-unicode-supported": "^1.2.0"
+ }
+ },
+ "get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ=="
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "inquirer": {
+ "version": "9.2.6",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.6.tgz",
+ "integrity": "sha512-y71l237eJJKS4rl7sQcEUiMhrR0pB/ZnRMMTxLpjJhWL4hdWCT03a6jJnC1w6qIPSRZWEozuieGt3v7XaEJYFw==",
+ "requires": {
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^5.2.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^4.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^5.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "1.0.0",
+ "ora": "^5.4.1",
+ "run-async": "^3.0.0",
+ "rxjs": "^7.8.1",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "through": "^2.3.6",
+ "wrap-ansi": "^6.0.1"
+ }
+ },
+ "is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
+ "is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "requires": {
+ "is-docker": "^3.0.0"
+ }
+ },
+ "is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
+ },
+ "is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="
+ },
+ "is-unicode-supported": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+ "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="
+ },
+ "is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "requires": {
+ "is-docker": "^2.0.0"
+ },
+ "dependencies": {
+ "is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="
+ }
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
+ }
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+ },
+ "mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="
+ },
+ "npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "requires": {
+ "path-key": "^4.0.0"
+ },
+ "dependencies": {
+ "path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="
+ }
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "requires": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ }
+ },
+ "ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "requires": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
+ }
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
+ },
+ "parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw=="
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+ },
+ "readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "requires": {
+ "execa": "^5.0.0"
+ },
+ "dependencies": {
+ "execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="
+ }
+ }
+ },
+ "run-async": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
+ "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q=="
+ },
+ "rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+ },
+ "titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ=="
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "tslib": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
+ "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA=="
+ },
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="
+ },
+ "untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw=="
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "requires": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ }
+ }
+}
diff --git a/remix.init/package.json b/remix.init/package.json
new file mode 100644
index 0000000..3a85b81
--- /dev/null
+++ b/remix.init/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "remix.init",
+ "private": true,
+ "main": "index.js",
+ "dependencies": {
+ "@iarna/toml": "^2.2.5",
+ "execa": "^7.1.1",
+ "inquirer": "^9.2.6",
+ "open": "^9.1.0",
+ "parse-github-url": "^1.0.2"
+ }
+}
diff --git a/server/dev-server.js b/server/dev-server.js
new file mode 100644
index 0000000..bc046be
--- /dev/null
+++ b/server/dev-server.js
@@ -0,0 +1,19 @@
+import { execa } from 'execa'
+
+if (process.env.NODE_ENV === 'production') {
+ await import('../server-build/index.js')
+} else {
+ const command =
+ 'tsx watch --clear-screen=false --ignore ".cache/**" --ignore "app/**" --ignore "vite.config.ts.timestamp-*" --ignore "build/**" --ignore "node_modules/**" --inspect ./index.js'
+ execa(command, {
+ stdio: ['ignore', 'inherit', 'inherit'],
+ shell: true,
+ env: {
+ FORCE_COLOR: true,
+ MOCKS: true,
+ ...process.env,
+ },
+ // https://github.com/sindresorhus/execa/issues/433
+ windowsHide: false,
+ })
+}
diff --git a/server/index.ts b/server/index.ts
new file mode 100644
index 0000000..4575e78
--- /dev/null
+++ b/server/index.ts
@@ -0,0 +1,283 @@
+import crypto from 'node:crypto'
+import { createRequestHandler } from '@remix-run/express'
+import { type ServerBuild } from '@remix-run/node'
+import { ip as ipAddress } from 'address'
+import chalk from 'chalk'
+import closeWithGrace from 'close-with-grace'
+import compression from 'compression'
+import express from 'express'
+import rateLimit from 'express-rate-limit'
+import getPort, { portNumbers } from 'get-port'
+import helmet from 'helmet'
+import morgan from 'morgan'
+
+const MODE = process.env.NODE_ENV ?? 'development'
+const IS_PROD = MODE === 'production'
+const IS_DEV = MODE === 'development'
+const ALLOW_INDEXING = process.env.ALLOW_INDEXING !== 'false'
+
+if (IS_PROD && process.env.SENTRY_DSN) {
+ void import('./utils/monitoring.js').then(({ init }) => init())
+}
+
+const viteDevServer = IS_PROD
+ ? undefined
+ : await import('vite').then((vite) =>
+ vite.createServer({
+ server: { middlewareMode: true },
+ }),
+ )
+
+const app = express()
+
+const getHost = (req: { get: (key: string) => string | undefined }) =>
+ req.get('X-Forwarded-Host') ?? req.get('host') ?? ''
+
+// fly is our proxy
+app.set('trust proxy', true)
+
+// ensure HTTPS only (X-Forwarded-Proto comes from Fly)
+app.use((req, res, next) => {
+ if (req.method !== 'GET') return next()
+ const proto = req.get('X-Forwarded-Proto')
+ const host = getHost(req)
+ if (proto === 'http') {
+ res.set('X-Forwarded-Proto', 'https')
+ res.redirect(`https://${host}${req.originalUrl}`)
+ return
+ }
+ next()
+})
+
+// no ending slashes for SEO reasons
+// https://github.com/epicweb-dev/epic-stack/discussions/108
+app.get('*', (req, res, next) => {
+ if (req.path.endsWith('/') && req.path.length > 1) {
+ const query = req.url.slice(req.path.length)
+ const safepath = req.path.slice(0, -1).replace(/\/+/g, '/')
+ res.redirect(302, safepath + query)
+ } else {
+ next()
+ }
+})
+
+app.use(compression())
+
+// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header
+app.disable('x-powered-by')
+
+if (viteDevServer) {
+ app.use(viteDevServer.middlewares)
+} else {
+ // Remix fingerprints its assets so we can cache forever.
+ app.use(
+ '/assets',
+ express.static('build/client/assets', { immutable: true, maxAge: '1y' }),
+ )
+
+ // Everything else (like favicon.ico) is cached for an hour. You may want to be
+ // more aggressive with this caching.
+ app.use(express.static('build/client', { maxAge: '1h' }))
+}
+
+app.get(['/img/*', '/favicons/*'], (_req, res) => {
+ // if we made it past the express.static for these, then we're missing something.
+ // So we'll just send a 404 and won't bother calling other middleware.
+ return res.status(404).send('Not found')
+})
+
+morgan.token('url', (req) => decodeURIComponent(req.url ?? ''))
+app.use(
+ morgan('tiny', {
+ skip: (req, res) =>
+ res.statusCode === 200 &&
+ (req.url?.startsWith('/resources/note-images') ||
+ req.url?.startsWith('/resources/user-images') ||
+ req.url?.startsWith('/resources/healthcheck')),
+ }),
+)
+
+app.use((_, res, next) => {
+ res.locals.cspNonce = crypto.randomBytes(16).toString('hex')
+ next()
+})
+
+app.use(
+ helmet({
+ xPoweredBy: false,
+ referrerPolicy: { policy: 'same-origin' },
+ crossOriginEmbedderPolicy: false,
+ contentSecurityPolicy: {
+ // NOTE: Remove reportOnly when you're ready to enforce this CSP
+ reportOnly: true,
+ directives: {
+ 'connect-src': [
+ MODE === 'development' ? 'ws:' : null,
+ process.env.SENTRY_DSN ? '*.sentry.io' : null,
+ "'self'",
+ ].filter(Boolean),
+ 'font-src': ["'self'"],
+ 'frame-src': ["'self'"],
+ 'img-src': ["'self'", 'data:'],
+ 'script-src': [
+ "'strict-dynamic'",
+ "'self'",
+ // @ts-expect-error
+ (_, res) => `'nonce-${res.locals.cspNonce}'`,
+ ],
+ 'script-src-attr': [
+ // @ts-expect-error
+ (_, res) => `'nonce-${res.locals.cspNonce}'`,
+ ],
+ 'upgrade-insecure-requests': null,
+ },
+ },
+ }),
+)
+
+// When running tests or running in development, we want to effectively disable
+// rate limiting because playwright tests are very fast and we don't want to
+// have to wait for the rate limit to reset between tests.
+const maxMultiple =
+ !IS_PROD || process.env.PLAYWRIGHT_TEST_BASE_URL ? 10_000 : 1
+const rateLimitDefault = {
+ windowMs: 60 * 1000,
+ max: 1000 * maxMultiple,
+ standardHeaders: true,
+ legacyHeaders: false,
+ validate: { trustProxy: false },
+ // Malicious users can spoof their IP address which means we should not deault
+ // to trusting req.ip when hosted on Fly.io. However, users cannot spoof Fly-Client-Ip.
+ // When sitting behind a CDN such as cloudflare, replace fly-client-ip with the CDN
+ // specific header such as cf-connecting-ip
+ keyGenerator: (req: express.Request) => {
+ return req.get('fly-client-ip') ?? `${req.ip}`
+ },
+}
+
+const strongestRateLimit = rateLimit({
+ ...rateLimitDefault,
+ windowMs: 60 * 1000,
+ max: 10 * maxMultiple,
+})
+
+const strongRateLimit = rateLimit({
+ ...rateLimitDefault,
+ windowMs: 60 * 1000,
+ max: 100 * maxMultiple,
+})
+
+const generalRateLimit = rateLimit(rateLimitDefault)
+app.use((req, res, next) => {
+ const strongPaths = [
+ '/login',
+ '/signup',
+ '/verify',
+ '/admin',
+ '/onboarding',
+ '/reset-password',
+ '/settings/profile',
+ '/resources/login',
+ '/resources/verify',
+ ]
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
+ if (strongPaths.some((p) => req.path.includes(p))) {
+ return strongestRateLimit(req, res, next)
+ }
+ return strongRateLimit(req, res, next)
+ }
+
+ // the verify route is a special case because it's a GET route that
+ // can have a token in the query string
+ if (req.path.includes('/verify')) {
+ return strongestRateLimit(req, res, next)
+ }
+
+ return generalRateLimit(req, res, next)
+})
+
+async function getBuild() {
+ try {
+ const build = viteDevServer
+ ? await viteDevServer.ssrLoadModule('virtual:remix/server-build')
+ : // @ts-expect-error - the file might not exist yet but it will
+ // eslint-disable-next-line import/no-unresolved
+ await import('../build/server/index.js')
+
+ return { build: build as unknown as ServerBuild, error: null }
+ } catch (error) {
+ // Catch error and return null to make express happy and avoid an unrecoverable crash
+ console.error('Error creating build:', error)
+ return { error: error, build: null as unknown as ServerBuild }
+ }
+}
+
+if (!ALLOW_INDEXING) {
+ app.use((_, res, next) => {
+ res.set('X-Robots-Tag', 'noindex, nofollow')
+ next()
+ })
+}
+
+app.all(
+ '*',
+ createRequestHandler({
+ getLoadContext: (_: any, res: any) => ({
+ cspNonce: res.locals.cspNonce,
+ serverBuild: getBuild(),
+ }),
+ mode: MODE,
+ build: async () => {
+ const { error, build } = await getBuild()
+ // gracefully "catch" the error
+ if (error) {
+ throw error
+ }
+ return build
+ },
+ }),
+)
+
+const desiredPort = Number(process.env.PORT || 3000)
+const portToUse = await getPort({
+ port: portNumbers(desiredPort, desiredPort + 100),
+})
+const portAvailable = desiredPort === portToUse
+if (!portAvailable && !IS_DEV) {
+ console.log(`â ď¸ Port ${desiredPort} is not available.`)
+ process.exit(1)
+}
+
+const server = app.listen(portToUse, () => {
+ if (!portAvailable) {
+ console.warn(
+ chalk.yellow(
+ `â ď¸ Port ${desiredPort} is not available, using ${portToUse} instead.`,
+ ),
+ )
+ }
+ console.log(`đ We have liftoff!`)
+ const localUrl = `http://localhost:${portToUse}`
+ let lanUrl: string | null = null
+ const localIp = ipAddress() ?? 'Unknown'
+ // Check if the address is a private ip
+ // https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
+ // https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/react-dev-utils/WebpackDevServerUtils.js#LL48C9-L54C10
+ if (/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(localIp)) {
+ lanUrl = `http://${localIp}:${portToUse}`
+ }
+
+ console.log(
+ `
+${chalk.bold('Local:')} ${chalk.cyan(localUrl)}
+${lanUrl ? `${chalk.bold('On Your Network:')} ${chalk.cyan(lanUrl)}` : ''}
+${chalk.bold('Press Ctrl+C to stop')}
+ `.trim(),
+ )
+})
+
+closeWithGrace(async () => {
+ await new Promise((resolve, reject) => {
+ server.close((e) => (e ? reject(e) : resolve('ok')))
+ })
+})
diff --git a/server/utils/monitoring.ts b/server/utils/monitoring.ts
new file mode 100644
index 0000000..e314e32
--- /dev/null
+++ b/server/utils/monitoring.ts
@@ -0,0 +1,42 @@
+import { nodeProfilingIntegration } from '@sentry/profiling-node'
+import Sentry from '@sentry/remix'
+
+export function init() {
+ Sentry.init({
+ dsn: process.env.SENTRY_DSN,
+ environment: process.env.NODE_ENV,
+ tracesSampleRate: process.env.NODE_ENV === 'production' ? 1 : 0,
+ autoInstrumentRemix: true,
+ denyUrls: [
+ /\/resources\/healthcheck/,
+ // TODO: be smarter about the public assets...
+ /\/build\//,
+ /\/favicons\//,
+ /\/img\//,
+ /\/fonts\//,
+ /\/favicon.ico/,
+ /\/site\.webmanifest/,
+ ],
+ integrations: [
+ Sentry.httpIntegration(),
+ Sentry.prismaIntegration(),
+ nodeProfilingIntegration(),
+ ],
+ tracesSampler(samplingContext) {
+ // ignore healthcheck transactions by other services (consul, etc.)
+ if (samplingContext.request?.url?.includes('/resources/healthcheck')) {
+ return 0
+ }
+ return 1
+ },
+ beforeSendTransaction(event) {
+ // ignore all healthcheck related transactions
+ // note that name of header here is case-sensitive
+ if (event.request?.headers?.['x-healthcheck'] === 'true') {
+ return null
+ }
+
+ return event
+ },
+ })
+}
diff --git a/tailwind.config.ts b/tailwind.config.ts
new file mode 100644
index 0000000..0c4695b
--- /dev/null
+++ b/tailwind.config.ts
@@ -0,0 +1,22 @@
+import { type Config } from 'tailwindcss'
+import animatePlugin from 'tailwindcss-animate'
+import radixPlugin from 'tailwindcss-radix'
+import { marketingPreset } from './app/routes/_marketing+/tailwind-preset'
+import { extendedTheme } from './app/utils/extended-theme.ts'
+
+export default {
+ content: ['./app/**/*.{ts,tsx,jsx,js}'],
+ darkMode: 'class',
+ theme: {
+ container: {
+ center: true,
+ padding: '2rem',
+ screens: {
+ '2xl': '1400px',
+ },
+ },
+ extend: extendedTheme,
+ },
+ presets: [marketingPreset],
+ plugins: [animatePlugin, radixPlugin],
+} satisfies Config
diff --git a/tests/db-utils.ts b/tests/db-utils.ts
new file mode 100644
index 0000000..5264125
--- /dev/null
+++ b/tests/db-utils.ts
@@ -0,0 +1,177 @@
+import fs from 'node:fs'
+import { faker } from '@faker-js/faker'
+import bcrypt from 'bcryptjs'
+import Database from 'better-sqlite3'
+import { UniqueEnforcer } from 'enforce-unique'
+
+const uniqueUsernameEnforcer = new UniqueEnforcer()
+
+export function createUser() {
+ const firstName = faker.person.firstName()
+ const lastName = faker.person.lastName()
+
+ const username = uniqueUsernameEnforcer
+ .enforce(() => {
+ return (
+ faker.string.alphanumeric({ length: 2 }) +
+ '_' +
+ faker.internet.userName({
+ firstName: firstName.toLowerCase(),
+ lastName: lastName.toLowerCase(),
+ })
+ )
+ })
+ .slice(0, 20)
+ .toLowerCase()
+ .replace(/[^a-z0-9_]/g, '_')
+ return {
+ username,
+ name: `${firstName} ${lastName}`,
+ email: `${username}@example.com`,
+ }
+}
+
+export function createPassword(password: string = faker.internet.password()) {
+ return {
+ hash: bcrypt.hashSync(password, 10),
+ }
+}
+
+let noteImages: Array>> | undefined
+export async function getNoteImages() {
+ if (noteImages) return noteImages
+
+ noteImages = await Promise.all([
+ img({
+ altText: 'a nice country house',
+ filepath: './tests/fixtures/images/notes/0.png',
+ }),
+ img({
+ altText: 'a city scape',
+ filepath: './tests/fixtures/images/notes/1.png',
+ }),
+ img({
+ altText: 'a sunrise',
+ filepath: './tests/fixtures/images/notes/2.png',
+ }),
+ img({
+ altText: 'a group of friends',
+ filepath: './tests/fixtures/images/notes/3.png',
+ }),
+ img({
+ altText: 'friends being inclusive of someone who looks lonely',
+ filepath: './tests/fixtures/images/notes/4.png',
+ }),
+ img({
+ altText: 'an illustration of a hot air balloon',
+ filepath: './tests/fixtures/images/notes/5.png',
+ }),
+ img({
+ altText:
+ 'an office full of laptops and other office equipment that look like it was abandoned in a rush out of the building in an emergency years ago.',
+ filepath: './tests/fixtures/images/notes/6.png',
+ }),
+ img({
+ altText: 'a rusty lock',
+ filepath: './tests/fixtures/images/notes/7.png',
+ }),
+ img({
+ altText: 'something very happy in nature',
+ filepath: './tests/fixtures/images/notes/8.png',
+ }),
+ img({
+ altText: `someone at the end of a cry session who's starting to feel a little better.`,
+ filepath: './tests/fixtures/images/notes/9.png',
+ }),
+ ])
+
+ return noteImages
+}
+
+let userImages: Array>> | undefined
+export async function getUserImages() {
+ if (userImages) return userImages
+
+ userImages = await Promise.all(
+ Array.from({ length: 10 }, (_, index) =>
+ img({ filepath: `./tests/fixtures/images/user/${index}.jpg` }),
+ ),
+ )
+
+ return userImages
+}
+
+export async function img({
+ altText,
+ filepath,
+}: {
+ altText?: string
+ filepath: string
+}) {
+ return {
+ altText,
+ contentType: filepath.endsWith('.png') ? 'image/png' : 'image/jpeg',
+ blob: await fs.promises.readFile(filepath),
+ }
+}
+
+let _migrationSqls: Array> | undefined
+async function getMigrationSqls() {
+ if (_migrationSqls) return _migrationSqls
+
+ const migrationSqls: Array> = []
+ const migrationPaths = (await fs.promises.readdir('prisma/migrations'))
+ .filter((dir) => dir !== 'migration_lock.toml')
+ .map((dir) => `prisma/migrations/${dir}/migration.sql`)
+
+ for (const path of migrationPaths) {
+ const sql = await fs.promises.readFile(path, 'utf8')
+ const statements = sql
+ .split(';')
+ .map((statement) => statement.trim())
+ .filter(Boolean)
+ migrationSqls.push(statements)
+ }
+
+ _migrationSqls = migrationSqls
+
+ return migrationSqls
+}
+
+export async function cleanupDb() {
+ const db = new Database(process.env.DATABASE_URL!.replace('file:', ''))
+
+ try {
+ // Disable FK constraints to avoid relation conflicts during deletion
+ db.exec('PRAGMA foreign_keys = OFF')
+
+ // Get all table names
+ const tables = db
+ .prepare(
+ `
+ SELECT name FROM sqlite_master
+ WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_prisma_migrations'
+ `,
+ )
+ .all() as { name: string }[]
+
+ // Delete tables except the ones that are excluded above
+ for (const { name } of tables) {
+ db.exec(`DROP TABLE IF EXISTS "${name}"`)
+ }
+
+ // Get migration SQLs and run each migration
+ const migrationSqls = await getMigrationSqls()
+ for (const statements of migrationSqls) {
+ // Run each sql statement in the migration
+ db.transaction(() => {
+ for (const statement of statements) {
+ db.exec(statement)
+ }
+ })()
+ }
+ } finally {
+ db.exec('PRAGMA foreign_keys = ON')
+ db.close()
+ }
+}
diff --git a/tests/e2e/2fa.test.ts b/tests/e2e/2fa.test.ts
new file mode 100644
index 0000000..e0fa6ed
--- /dev/null
+++ b/tests/e2e/2fa.test.ts
@@ -0,0 +1,52 @@
+import { faker } from '@faker-js/faker'
+import { generateTOTP } from '#app/utils/totp.server.ts'
+import { expect, test } from '#tests/playwright-utils.ts'
+
+test('Users can add 2FA to their account and use it when logging in', async ({
+ page,
+ login,
+}) => {
+ const password = faker.internet.password()
+ const user = await login({ password })
+ await page.goto('/settings/profile')
+
+ await page.getByRole('link', { name: /enable 2fa/i }).click()
+
+ await expect(page).toHaveURL(`/settings/profile/two-factor`)
+ const main = page.getByRole('main')
+ await main.getByRole('button', { name: /enable 2fa/i }).click()
+ const otpUriString = await main
+ .getByLabel(/One-Time Password URI/i)
+ .innerText()
+
+ const otpUri = new URL(otpUriString)
+ const options = Object.fromEntries(otpUri.searchParams)
+
+ await main
+ .getByRole('textbox', { name: /code/i })
+ .fill(generateTOTP(options).otp)
+ await main.getByRole('button', { name: /submit/i }).click()
+
+ await expect(main).toHaveText(/You have enabled two-factor authentication./i)
+ await expect(main.getByRole('link', { name: /disable 2fa/i })).toBeVisible()
+
+ await page.getByRole('link', { name: user.name ?? user.username }).click()
+ await page.getByRole('button', { name: /logout/i }).click()
+ await expect(page).toHaveURL(`/`)
+
+ await page.goto('/login')
+ await expect(page).toHaveURL(`/login`)
+ await page.getByRole('textbox', { name: /username/i }).fill(user.username)
+ await page.getByLabel(/^password$/i).fill(password)
+ await page.getByRole('button', { name: /log in/i }).click()
+
+ await page
+ .getByRole('textbox', { name: /code/i })
+ .fill(generateTOTP(options).otp)
+
+ await page.getByRole('button', { name: /submit/i }).click()
+
+ await expect(
+ page.getByRole('link', { name: user.name ?? user.username }),
+ ).toBeVisible()
+})
diff --git a/tests/e2e/error-boundary.test.ts b/tests/e2e/error-boundary.test.ts
new file mode 100644
index 0000000..5254f0f
--- /dev/null
+++ b/tests/e2e/error-boundary.test.ts
@@ -0,0 +1,9 @@
+import { expect, test } from '#tests/playwright-utils.ts'
+
+test('Test root error boundary caught', async ({ page }) => {
+ const pageUrl = '/does-not-exist'
+ const res = await page.goto(pageUrl)
+
+ expect(res?.status()).toBe(404)
+ await expect(page.getByText(/We can't find this page/i)).toBeVisible()
+})
diff --git a/tests/e2e/note-images.test.ts b/tests/e2e/note-images.test.ts
new file mode 100644
index 0000000..5b1addc
--- /dev/null
+++ b/tests/e2e/note-images.test.ts
@@ -0,0 +1,140 @@
+import fs from 'node:fs'
+import { faker } from '@faker-js/faker'
+import { type NoteImage, type Note } from '@prisma/client'
+import { prisma } from '#app/utils/db.server.ts'
+import { expect, test } from '#tests/playwright-utils.ts'
+
+test('Users can create note with an image', async ({ page, login }) => {
+ const user = await login()
+ await page.goto(`/users/${user.username}/notes`)
+
+ const newNote = createNote()
+ const altText = 'cute koala'
+ await page.getByRole('link', { name: 'new note' }).click()
+
+ // fill in form and submit
+ await page.getByRole('textbox', { name: 'title' }).fill(newNote.title)
+ await page.getByRole('textbox', { name: 'content' }).fill(newNote.content)
+ await page
+ .getByLabel('image')
+ .nth(0)
+ .setInputFiles('tests/fixtures/images/kody-notes/cute-koala.png')
+ await page.getByRole('textbox', { name: 'alt text' }).fill(altText)
+
+ await page.getByRole('button', { name: 'submit' }).click()
+ await expect(page).toHaveURL(new RegExp(`/users/${user.username}/notes/.*`))
+ await expect(page.getByRole('heading', { name: newNote.title })).toBeVisible()
+ await expect(page.getByAltText(altText)).toBeVisible()
+})
+
+test('Users can create note with multiple images', async ({ page, login }) => {
+ const user = await login()
+ await page.goto(`/users/${user.username}/notes`)
+
+ const newNote = createNote()
+ const altText1 = 'cute koala'
+ const altText2 = 'koala coder'
+ await page.getByRole('link', { name: 'new note' }).click()
+
+ // fill in form and submit
+ await page.getByRole('textbox', { name: 'title' }).fill(newNote.title)
+ await page.getByRole('textbox', { name: 'content' }).fill(newNote.content)
+ await page
+ .getByLabel('image')
+ .nth(0)
+ .setInputFiles('tests/fixtures/images/kody-notes/cute-koala.png')
+ await page.getByLabel('alt text').nth(0).fill(altText1)
+ await page.getByRole('button', { name: 'add image' }).click()
+
+ await page
+ .getByLabel('image')
+ .nth(1)
+ .setInputFiles('tests/fixtures/images/kody-notes/koala-coder.png')
+ await page.getByLabel('alt text').nth(1).fill(altText2)
+
+ await page.getByRole('button', { name: 'submit' }).click()
+ await expect(page).toHaveURL(new RegExp(`/users/${user.username}/notes/.*`))
+ await expect(page.getByRole('heading', { name: newNote.title })).toBeVisible()
+ await expect(page.getByAltText(altText1)).toBeVisible()
+ await expect(page.getByAltText(altText2)).toBeVisible()
+})
+
+test('Users can edit note image', async ({ page, login }) => {
+ const user = await login()
+
+ const note = await prisma.note.create({
+ select: { id: true },
+ data: {
+ ...createNoteWithImage(),
+ ownerId: user.id,
+ },
+ })
+ await page.goto(`/users/${user.username}/notes/${note.id}`)
+
+ // edit the image
+ await page.getByRole('link', { name: 'Edit', exact: true }).click()
+ const updatedImage = {
+ altText: 'koala coder',
+ location: 'tests/fixtures/images/kody-notes/koala-coder.png',
+ }
+ await page.getByLabel('image').nth(0).setInputFiles(updatedImage.location)
+ await page.getByLabel('alt text').nth(0).fill(updatedImage.altText)
+ await page.getByRole('button', { name: 'submit' }).click()
+
+ await expect(page).toHaveURL(`/users/${user.username}/notes/${note.id}`)
+ await expect(page.getByAltText(updatedImage.altText)).toBeVisible()
+})
+
+test('Users can delete note image', async ({ page, login }) => {
+ const user = await login()
+
+ const note = await prisma.note.create({
+ select: { id: true, title: true },
+ data: {
+ ...createNoteWithImage(),
+ ownerId: user.id,
+ },
+ })
+ await page.goto(`/users/${user.username}/notes/${note.id}`)
+
+ await expect(page.getByRole('heading', { name: note.title })).toBeVisible()
+ // find image tags
+ const images = page
+ .getByRole('main')
+ .getByRole('list')
+ .getByRole('listitem')
+ .getByRole('img')
+ const countBefore = await images.count()
+ await page.getByRole('link', { name: 'Edit', exact: true }).click()
+ await page.getByRole('button', { name: 'remove image' }).click()
+ await page.getByRole('button', { name: 'submit' }).click()
+ await expect(page).toHaveURL(`/users/${user.username}/notes/${note.id}`)
+ const countAfter = await images.count()
+ expect(countAfter).toEqual(countBefore - 1)
+})
+
+function createNote() {
+ return {
+ title: faker.lorem.words(3),
+ content: faker.lorem.paragraphs(3),
+ } satisfies Omit
+}
+function createNoteWithImage() {
+ return {
+ ...createNote(),
+ images: {
+ create: {
+ altText: 'cute koala',
+ contentType: 'image/png',
+ blob: fs.readFileSync(
+ 'tests/fixtures/images/kody-notes/cute-koala.png',
+ ),
+ },
+ },
+ } satisfies Omit<
+ Note,
+ 'id' | 'createdAt' | 'updatedAt' | 'type' | 'ownerId'
+ > & {
+ images: { create: Pick }
+ }
+}
diff --git a/tests/e2e/onboarding.test.ts b/tests/e2e/onboarding.test.ts
new file mode 100644
index 0000000..92064e3
--- /dev/null
+++ b/tests/e2e/onboarding.test.ts
@@ -0,0 +1,431 @@
+import { invariant } from '@epic-web/invariant'
+import { faker } from '@faker-js/faker'
+import { prisma } from '#app/utils/db.server.ts'
+import {
+ normalizeEmail,
+ normalizeUsername,
+} from '#app/utils/providers/provider'
+import {
+ USERNAME_MAX_LENGTH,
+ USERNAME_MIN_LENGTH,
+} from '#app/utils/user-validation'
+import { readEmail } from '#tests/mocks/utils.ts'
+import { createUser, expect, test as base } from '#tests/playwright-utils.ts'
+
+const URL_REGEX = /(?https?:\/\/[^\s$.?#].[^\s]*)/
+const CODE_REGEX = /Here's your verification code: (?[\d\w]+)/
+function extractUrl(text: string) {
+ const match = text.match(URL_REGEX)
+ return match?.groups?.url
+}
+
+const test = base.extend<{
+ getOnboardingData(): {
+ username: string
+ name: string
+ email: string
+ password: string
+ }
+}>({
+ getOnboardingData: async ({}, use) => {
+ const userData = createUser()
+ await use(() => {
+ const onboardingData = {
+ ...userData,
+ password: faker.internet.password(),
+ }
+ return onboardingData
+ })
+ await prisma.user.deleteMany({ where: { username: userData.username } })
+ },
+})
+
+test('onboarding with link', async ({ page, getOnboardingData }) => {
+ const onboardingData = getOnboardingData()
+
+ await page.goto('/')
+
+ await page.getByRole('link', { name: /log in/i }).click()
+ await expect(page).toHaveURL(`/login`)
+
+ const createAccountLink = page.getByRole('link', {
+ name: /create an account/i,
+ })
+ await createAccountLink.click()
+
+ await expect(page).toHaveURL(`/signup`)
+
+ const emailTextbox = page.getByRole('textbox', { name: /email/i })
+ await emailTextbox.click()
+ await emailTextbox.fill(onboardingData.email)
+
+ await page.getByRole('button', { name: /submit/i }).click()
+ await expect(
+ page.getByRole('button', { name: /submit/i, disabled: true }),
+ ).toBeVisible()
+ await expect(page.getByText(/check your email/i)).toBeVisible()
+
+ const email = await readEmail(onboardingData.email)
+ invariant(email, 'Email not found')
+ expect(email.to).toBe(onboardingData.email.toLowerCase())
+ expect(email.from).toBe('hello@epicstack.dev')
+ expect(email.subject).toMatch(/welcome/i)
+ const onboardingUrl = extractUrl(email.text)
+ invariant(onboardingUrl, 'Onboarding URL not found')
+ await page.goto(onboardingUrl)
+
+ await expect(page).toHaveURL(/\/verify/)
+
+ await page
+ .getByRole('main')
+ .getByRole('button', { name: /submit/i })
+ .click()
+
+ await expect(page).toHaveURL(`/onboarding`)
+ await page
+ .getByRole('textbox', { name: /^username/i })
+ .fill(onboardingData.username)
+
+ await page.getByRole('textbox', { name: /^name/i }).fill(onboardingData.name)
+
+ await page.getByLabel(/^password/i).fill(onboardingData.password)
+
+ await page.getByLabel(/^confirm password/i).fill(onboardingData.password)
+
+ await page.getByLabel(/terms/i).check()
+
+ await page.getByLabel(/remember me/i).check()
+
+ await page.getByRole('button', { name: /Create an account/i }).click()
+
+ await expect(page).toHaveURL(`/`)
+
+ await page.getByRole('link', { name: onboardingData.name }).click()
+ await page.getByRole('menuitem', { name: /profile/i }).click()
+
+ await expect(page).toHaveURL(`/users/${onboardingData.username}`)
+
+ await page.getByRole('link', { name: onboardingData.name }).click()
+ await page.getByRole('menuitem', { name: /logout/i }).click()
+ await expect(page).toHaveURL(`/`)
+})
+
+test('onboarding with a short code', async ({ page, getOnboardingData }) => {
+ const onboardingData = getOnboardingData()
+
+ await page.goto('/signup')
+
+ const emailTextbox = page.getByRole('textbox', { name: /email/i })
+ await emailTextbox.click()
+ await emailTextbox.fill(onboardingData.email)
+
+ await page.getByRole('button', { name: /submit/i }).click()
+ await expect(
+ page.getByRole('button', { name: /submit/i, disabled: true }),
+ ).toBeVisible()
+ await expect(page.getByText(/check your email/i)).toBeVisible()
+
+ const email = await readEmail(onboardingData.email)
+ invariant(email, 'Email not found')
+ expect(email.to).toBe(onboardingData.email.toLowerCase())
+ expect(email.from).toBe('hello@epicstack.dev')
+ expect(email.subject).toMatch(/welcome/i)
+ const codeMatch = email.text.match(CODE_REGEX)
+ const code = codeMatch?.groups?.code
+ invariant(code, 'Onboarding code not found')
+ await page.getByRole('textbox', { name: /code/i }).fill(code)
+ await page.getByRole('button', { name: /submit/i }).click()
+
+ await expect(page).toHaveURL(`/onboarding`)
+})
+
+test('completes onboarding after GitHub OAuth given valid user details', async ({
+ page,
+ prepareGitHubUser,
+}) => {
+ const ghUser = await prepareGitHubUser()
+
+ // let's verify we do not have user with that email in our system:
+ expect(
+ await prisma.user.findUnique({
+ where: { email: normalizeEmail(ghUser.primaryEmail) },
+ }),
+ ).toBeNull()
+
+ await page.goto('/signup')
+ await page.getByRole('button', { name: /signup with github/i }).click()
+
+ await expect(page).toHaveURL(/\/onboarding\/github/)
+ await expect(
+ page.getByText(new RegExp(`welcome aboard ${ghUser.primaryEmail}`, 'i')),
+ ).toBeVisible()
+
+ // fields are pre-populated for the user, so we only need to accept
+ // terms of service and hit the 'crete an account' button
+ const usernameInput = page.getByRole('textbox', { name: /username/i })
+ await expect(usernameInput).toHaveValue(
+ normalizeUsername(ghUser.profile.login),
+ )
+ await expect(page.getByRole('textbox', { name: /^name/i })).toHaveValue(
+ ghUser.profile.name,
+ )
+ const createAccountButton = page.getByRole('button', {
+ name: /create an account/i,
+ })
+
+ await page
+ .getByLabel(/do you agree to our terms of service and privacy policy/i)
+ .check()
+ await createAccountButton.click()
+ await expect(page).toHaveURL(/signup/i)
+
+ // we are still on the 'signup' route since that
+ // was the referrer and no 'redirectTo' has been specified
+ await expect(page).toHaveURL('/signup')
+ await expect(page.getByText(/thanks for signing up/i)).toBeVisible()
+
+ // internally, a user has been created:
+ await prisma.user.findUniqueOrThrow({
+ where: { email: normalizeEmail(ghUser.primaryEmail) },
+ })
+})
+
+test('logs user in after GitHub OAuth if they are already registered', async ({
+ page,
+ prepareGitHubUser,
+}) => {
+ const ghUser = await prepareGitHubUser()
+
+ // let's verify we do not have user with that email in our system ...
+ expect(
+ await prisma.user.findUnique({
+ where: { email: normalizeEmail(ghUser.primaryEmail) },
+ }),
+ ).toBeNull()
+ // ... and create one:
+ const name = faker.person.fullName()
+ const user = await prisma.user.create({
+ select: { id: true, name: true },
+ data: {
+ email: normalizeEmail(ghUser.primaryEmail),
+ username: normalizeUsername(ghUser.profile.login),
+ name,
+ },
+ })
+
+ // let's verify there is no connection between the GitHub user
+ // and out app's user:
+ const connection = await prisma.connection.findFirst({
+ where: { providerName: 'github', userId: user.id },
+ })
+ expect(connection).toBeNull()
+
+ await page.goto('/signup')
+ await page.getByRole('button', { name: /signup with github/i }).click()
+
+ await expect(page).toHaveURL(`/`)
+ await expect(
+ page.getByText(
+ new RegExp(
+ `your "${ghUser!.profile.login}" github account has been connected`,
+ 'i',
+ ),
+ ),
+ ).toBeVisible()
+
+ // internally, a connection (rather than a new user) has been created:
+ await prisma.connection.findFirstOrThrow({
+ where: { providerName: 'github', userId: user.id },
+ })
+})
+
+test('shows help texts on entering invalid details on onboarding page after GitHub OAuth', async ({
+ page,
+ prepareGitHubUser,
+}) => {
+ const ghUser = await prepareGitHubUser()
+
+ await page.goto('/signup')
+ await page.getByRole('button', { name: /signup with github/i }).click()
+
+ await expect(page).toHaveURL(/\/onboarding\/github/)
+ await expect(
+ page.getByText(new RegExp(`welcome aboard ${ghUser.primaryEmail}`, 'i')),
+ ).toBeVisible()
+
+ const usernameInput = page.getByRole('textbox', { name: /username/i })
+
+ // notice, how button is currently in 'idle' (neutral) state and so has got no companion
+ const createAccountButton = page.getByRole('button', {
+ name: /create an account/i,
+ })
+ await expect(createAccountButton.getByRole('status')).not.toBeVisible()
+ await expect(createAccountButton.getByText('error')).not.toBeAttached()
+
+ // invalid chars in username
+ await usernameInput.fill('U$er_name') // $ is invalid char, see app/utils/user-validation.ts.
+ await createAccountButton.click()
+
+ await expect(createAccountButton.getByRole('status')).toBeVisible()
+ await expect(createAccountButton.getByText('error')).toBeAttached()
+ await expect(
+ page.getByText(
+ /username can only include letters, numbers, and underscores/i,
+ ),
+ ).toBeVisible()
+ // but we also never checked that privacy consent box
+ await expect(
+ page.getByText(
+ /you must agree to the terms of service and privacy policy/i,
+ ),
+ ).toBeVisible()
+ await expect(page).toHaveURL(/\/onboarding\/github/)
+
+ // empty username
+ await usernameInput.fill('')
+ await createAccountButton.click()
+ await expect(page.getByText(/username is required/i)).toBeVisible()
+ await expect(page).toHaveURL(/\/onboarding\/github/)
+
+ // too short username
+ await usernameInput.fill(
+ faker.string.alphanumeric({ length: USERNAME_MIN_LENGTH - 1 }),
+ )
+ await createAccountButton.click()
+ await expect(page.getByText(/username is too short/i)).toBeVisible()
+
+ // too long username
+ await usernameInput.fill(
+ faker.string.alphanumeric({
+ length: USERNAME_MAX_LENGTH + 1,
+ }),
+ )
+ // we are truncating the user's input
+ expect((await usernameInput.inputValue()).length).toBe(USERNAME_MAX_LENGTH)
+ await createAccountButton.click()
+ await expect(page.getByText(/username is too long/i)).not.toBeVisible()
+
+ // still unchecked 'terms of service' checkbox
+ await usernameInput.fill(
+ normalizeUsername(`U5er_name_0k_${faker.person.lastName()}`),
+ )
+ await createAccountButton.click()
+ await expect(
+ page.getByText(/must agree to the terms of service and privacy policy/i),
+ ).toBeVisible()
+ await expect(page).toHaveURL(/\/onboarding\/github/)
+
+ // we are all set up and ...
+ await page
+ .getByLabel(/do you agree to our terms of service and privacy policy/i)
+ .check()
+ await createAccountButton.click()
+ await expect(createAccountButton.getByText('error')).not.toBeAttached()
+
+ // ... sign up is successful!
+ await expect(page.getByText(/thanks for signing up/i)).toBeVisible()
+})
+
+test('login as existing user', async ({ page, insertNewUser }) => {
+ const password = faker.internet.password()
+ const user = await insertNewUser({ password })
+ invariant(user.name, 'User name not found')
+ await page.goto('/login')
+ await page.getByRole('textbox', { name: /username/i }).fill(user.username)
+ await page.getByLabel(/^password$/i).fill(password)
+ await page.getByRole('button', { name: /log in/i }).click()
+ await expect(page).toHaveURL(`/`)
+
+ await expect(page.getByRole('link', { name: user.name })).toBeVisible()
+})
+
+test('reset password with a link', async ({ page, insertNewUser }) => {
+ const originalPassword = faker.internet.password()
+ const user = await insertNewUser({ password: originalPassword })
+ invariant(user.name, 'User name not found')
+ await page.goto('/login')
+
+ await page.getByRole('link', { name: /forgot password/i }).click()
+ await expect(page).toHaveURL('/forgot-password')
+
+ await expect(
+ page.getByRole('heading', { name: /forgot password/i }),
+ ).toBeVisible()
+ await page.getByRole('textbox', { name: /username/i }).fill(user.username)
+ await page.getByRole('button', { name: /recover password/i }).click()
+ await expect(
+ page.getByRole('button', { name: /recover password/i, disabled: true }),
+ ).toBeVisible()
+ await expect(page.getByText(/check your email/i)).toBeVisible()
+
+ const email = await readEmail(user.email)
+ invariant(email, 'Email not found')
+ expect(email.subject).toMatch(/password reset/i)
+ expect(email.to).toBe(user.email.toLowerCase())
+ expect(email.from).toBe('hello@epicstack.dev')
+ const resetPasswordUrl = extractUrl(email.text)
+ invariant(resetPasswordUrl, 'Reset password URL not found')
+ await page.goto(resetPasswordUrl)
+
+ await expect(page).toHaveURL(/\/verify/)
+
+ await page
+ .getByRole('main')
+ .getByRole('button', { name: /submit/i })
+ .click()
+
+ await expect(page).toHaveURL(`/reset-password`)
+ const newPassword = faker.internet.password()
+ await page.getByLabel(/^new password$/i).fill(newPassword)
+ await page.getByLabel(/^confirm password$/i).fill(newPassword)
+
+ await page.getByRole('button', { name: /reset password/i }).click()
+ await expect(
+ page.getByRole('button', { name: /reset password/i, disabled: true }),
+ ).toBeVisible()
+
+ await expect(page).toHaveURL('/login')
+ await page.getByRole('textbox', { name: /username/i }).fill(user.username)
+ await page.getByLabel(/^password$/i).fill(originalPassword)
+ await page.getByRole('button', { name: /log in/i }).click()
+
+ await expect(page.getByText(/invalid username or password/i)).toBeVisible()
+
+ await page.getByLabel(/^password$/i).fill(newPassword)
+ await page.getByRole('button', { name: /log in/i }).click()
+
+ await expect(page).toHaveURL(`/`)
+
+ await expect(page.getByRole('link', { name: user.name })).toBeVisible()
+})
+
+test('reset password with a short code', async ({ page, insertNewUser }) => {
+ const user = await insertNewUser()
+ await page.goto('/login')
+
+ await page.getByRole('link', { name: /forgot password/i }).click()
+ await expect(page).toHaveURL('/forgot-password')
+
+ await expect(
+ page.getByRole('heading', { name: /forgot password/i }),
+ ).toBeVisible()
+ await page.getByRole('textbox', { name: /username/i }).fill(user.username)
+ await page.getByRole('button', { name: /recover password/i }).click()
+ await expect(
+ page.getByRole('button', { name: /recover password/i, disabled: true }),
+ ).toBeVisible()
+ await expect(page.getByText(/check your email/i)).toBeVisible()
+
+ const email = await readEmail(user.email)
+ invariant(email, 'Email not found')
+ expect(email.subject).toMatch(/password reset/i)
+ expect(email.to).toBe(user.email)
+ expect(email.from).toBe('hello@epicstack.dev')
+ const codeMatch = email.text.match(CODE_REGEX)
+ const code = codeMatch?.groups?.code
+ invariant(code, 'Reset Password code not found')
+ await page.getByRole('textbox', { name: /code/i }).fill(code)
+ await page.getByRole('button', { name: /submit/i }).click()
+
+ await expect(page).toHaveURL(`/reset-password`)
+})
diff --git a/tests/e2e/settings-profile.test.ts b/tests/e2e/settings-profile.test.ts
new file mode 100644
index 0000000..7af0a08
--- /dev/null
+++ b/tests/e2e/settings-profile.test.ts
@@ -0,0 +1,115 @@
+import { invariant } from '@epic-web/invariant'
+import { faker } from '@faker-js/faker'
+import { verifyUserPassword } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { readEmail } from '#tests/mocks/utils.ts'
+import { expect, test, createUser, waitFor } from '#tests/playwright-utils.ts'
+
+const CODE_REGEX = /Here's your verification code: (?[\d\w]+)/
+
+test('Users can update their basic info', async ({ page, login }) => {
+ await login()
+ await page.goto('/settings/profile')
+
+ const newUserData = createUser()
+
+ await page.getByRole('textbox', { name: /^name/i }).fill(newUserData.name)
+ await page
+ .getByRole('textbox', { name: /^username/i })
+ .fill(newUserData.username)
+
+ await page.getByRole('button', { name: /^save/i }).click()
+})
+
+test('Users can update their password', async ({ page, login }) => {
+ const oldPassword = faker.internet.password()
+ const newPassword = faker.internet.password()
+ const user = await login({ password: oldPassword })
+ await page.goto('/settings/profile')
+
+ await page.getByRole('link', { name: /change password/i }).click()
+
+ await page
+ .getByRole('textbox', { name: /^current password/i })
+ .fill(oldPassword)
+ await page.getByRole('textbox', { name: /^new password/i }).fill(newPassword)
+ await page
+ .getByRole('textbox', { name: /^confirm new password/i })
+ .fill(newPassword)
+
+ await page.getByRole('button', { name: /^change password/i }).click()
+
+ await expect(page).toHaveURL(`/settings/profile`)
+
+ const { username } = user
+ expect(
+ await verifyUserPassword({ username }, oldPassword),
+ 'Old password still works',
+ ).toEqual(null)
+ expect(
+ await verifyUserPassword({ username }, newPassword),
+ 'New password does not work',
+ ).toEqual({ id: user.id })
+})
+
+test('Users can update their profile photo', async ({ page, login }) => {
+ const user = await login()
+ await page.goto('/settings/profile')
+
+ const beforeSrc = await page
+ .getByRole('img', { name: user.name ?? user.username })
+ .getAttribute('src')
+
+ await page.getByRole('link', { name: /change profile photo/i }).click()
+
+ await expect(page).toHaveURL(`/settings/profile/photo`)
+
+ await page
+ .getByRole('textbox', { name: /change/i })
+ .setInputFiles('./tests/fixtures/images/user/kody.png')
+
+ await page.getByRole('button', { name: /save/i }).click()
+
+ await expect(
+ page,
+ 'Was not redirected after saving the profile photo',
+ ).toHaveURL(`/settings/profile`)
+
+ const afterSrc = await page
+ .getByRole('img', { name: user.name ?? user.username })
+ .getAttribute('src')
+
+ expect(beforeSrc).not.toEqual(afterSrc)
+})
+
+test('Users can change their email address', async ({ page, login }) => {
+ const preUpdateUser = await login()
+ const newEmailAddress = faker.internet.email().toLowerCase()
+ expect(preUpdateUser.email).not.toEqual(newEmailAddress)
+ await page.goto('/settings/profile')
+ await page.getByRole('link', { name: /change email/i }).click()
+ await page.getByRole('textbox', { name: /new email/i }).fill(newEmailAddress)
+ await page.getByRole('button', { name: /send confirmation/i }).click()
+ await expect(page.getByText(/check your email/i)).toBeVisible()
+ const email = await waitFor(() => readEmail(newEmailAddress), {
+ errorMessage: 'Confirmation email was not sent',
+ })
+ invariant(email, 'Email was not sent')
+ const codeMatch = email.text.match(CODE_REGEX)
+ const code = codeMatch?.groups?.code
+ invariant(code, 'Onboarding code not found')
+ await page.getByRole('textbox', { name: /code/i }).fill(code)
+ await page.getByRole('button', { name: /submit/i }).click()
+ await expect(page.getByText(/email changed/i)).toBeVisible()
+
+ const updatedUser = await prisma.user.findUnique({
+ where: { id: preUpdateUser.id },
+ select: { email: true },
+ })
+ invariant(updatedUser, 'Updated user not found')
+ expect(updatedUser.email).toBe(newEmailAddress)
+ const noticeEmail = await waitFor(() => readEmail(preUpdateUser.email), {
+ errorMessage: 'Notice email was not sent',
+ })
+ expect(noticeEmail.subject).toContain('changed')
+})
diff --git a/tests/fixtures/github/ghost.jpg b/tests/fixtures/github/ghost.jpg
new file mode 100644
index 0000000..e5c8bd5
Binary files /dev/null and b/tests/fixtures/github/ghost.jpg differ
diff --git a/tests/fixtures/images/kody-notes/cute-koala.png b/tests/fixtures/images/kody-notes/cute-koala.png
new file mode 100644
index 0000000..b322eb5
Binary files /dev/null and b/tests/fixtures/images/kody-notes/cute-koala.png differ
diff --git a/tests/fixtures/images/kody-notes/koala-coder.png b/tests/fixtures/images/kody-notes/koala-coder.png
new file mode 100644
index 0000000..63e6d59
Binary files /dev/null and b/tests/fixtures/images/kody-notes/koala-coder.png differ
diff --git a/tests/fixtures/images/kody-notes/koala-cuddle.png b/tests/fixtures/images/kody-notes/koala-cuddle.png
new file mode 100644
index 0000000..ccc1d3b
Binary files /dev/null and b/tests/fixtures/images/kody-notes/koala-cuddle.png differ
diff --git a/tests/fixtures/images/kody-notes/koala-eating.png b/tests/fixtures/images/kody-notes/koala-eating.png
new file mode 100644
index 0000000..00713e8
Binary files /dev/null and b/tests/fixtures/images/kody-notes/koala-eating.png differ
diff --git a/tests/fixtures/images/kody-notes/koala-mentor.png b/tests/fixtures/images/kody-notes/koala-mentor.png
new file mode 100644
index 0000000..9796b8c
Binary files /dev/null and b/tests/fixtures/images/kody-notes/koala-mentor.png differ
diff --git a/tests/fixtures/images/kody-notes/koala-soccer.png b/tests/fixtures/images/kody-notes/koala-soccer.png
new file mode 100644
index 0000000..9c0e809
Binary files /dev/null and b/tests/fixtures/images/kody-notes/koala-soccer.png differ
diff --git a/tests/fixtures/images/kody-notes/mountain.png b/tests/fixtures/images/kody-notes/mountain.png
new file mode 100644
index 0000000..115fb9c
Binary files /dev/null and b/tests/fixtures/images/kody-notes/mountain.png differ
diff --git a/tests/fixtures/images/notes/0.png b/tests/fixtures/images/notes/0.png
new file mode 100644
index 0000000..b04ba30
Binary files /dev/null and b/tests/fixtures/images/notes/0.png differ
diff --git a/tests/fixtures/images/notes/1.png b/tests/fixtures/images/notes/1.png
new file mode 100644
index 0000000..307f0a8
Binary files /dev/null and b/tests/fixtures/images/notes/1.png differ
diff --git a/tests/fixtures/images/notes/2.png b/tests/fixtures/images/notes/2.png
new file mode 100644
index 0000000..23b9822
Binary files /dev/null and b/tests/fixtures/images/notes/2.png differ
diff --git a/tests/fixtures/images/notes/3.png b/tests/fixtures/images/notes/3.png
new file mode 100644
index 0000000..ec4e949
Binary files /dev/null and b/tests/fixtures/images/notes/3.png differ
diff --git a/tests/fixtures/images/notes/4.png b/tests/fixtures/images/notes/4.png
new file mode 100644
index 0000000..138a0ad
Binary files /dev/null and b/tests/fixtures/images/notes/4.png differ
diff --git a/tests/fixtures/images/notes/5.png b/tests/fixtures/images/notes/5.png
new file mode 100644
index 0000000..bd2d0c1
Binary files /dev/null and b/tests/fixtures/images/notes/5.png differ
diff --git a/tests/fixtures/images/notes/6.png b/tests/fixtures/images/notes/6.png
new file mode 100644
index 0000000..4d34f94
Binary files /dev/null and b/tests/fixtures/images/notes/6.png differ
diff --git a/tests/fixtures/images/notes/7.png b/tests/fixtures/images/notes/7.png
new file mode 100644
index 0000000..2ccdd83
Binary files /dev/null and b/tests/fixtures/images/notes/7.png differ
diff --git a/tests/fixtures/images/notes/8.png b/tests/fixtures/images/notes/8.png
new file mode 100644
index 0000000..dfb7dab
Binary files /dev/null and b/tests/fixtures/images/notes/8.png differ
diff --git a/tests/fixtures/images/notes/9.png b/tests/fixtures/images/notes/9.png
new file mode 100644
index 0000000..1397419
Binary files /dev/null and b/tests/fixtures/images/notes/9.png differ
diff --git a/tests/fixtures/images/user/0.jpg b/tests/fixtures/images/user/0.jpg
new file mode 100644
index 0000000..d3a9d7a
Binary files /dev/null and b/tests/fixtures/images/user/0.jpg differ
diff --git a/tests/fixtures/images/user/1.jpg b/tests/fixtures/images/user/1.jpg
new file mode 100644
index 0000000..83c858c
Binary files /dev/null and b/tests/fixtures/images/user/1.jpg differ
diff --git a/tests/fixtures/images/user/2.jpg b/tests/fixtures/images/user/2.jpg
new file mode 100644
index 0000000..de2564f
Binary files /dev/null and b/tests/fixtures/images/user/2.jpg differ
diff --git a/tests/fixtures/images/user/3.jpg b/tests/fixtures/images/user/3.jpg
new file mode 100644
index 0000000..0e6a682
Binary files /dev/null and b/tests/fixtures/images/user/3.jpg differ
diff --git a/tests/fixtures/images/user/4.jpg b/tests/fixtures/images/user/4.jpg
new file mode 100644
index 0000000..a9feae7
Binary files /dev/null and b/tests/fixtures/images/user/4.jpg differ
diff --git a/tests/fixtures/images/user/5.jpg b/tests/fixtures/images/user/5.jpg
new file mode 100644
index 0000000..76c1183
Binary files /dev/null and b/tests/fixtures/images/user/5.jpg differ
diff --git a/tests/fixtures/images/user/6.jpg b/tests/fixtures/images/user/6.jpg
new file mode 100644
index 0000000..a5b1e8e
Binary files /dev/null and b/tests/fixtures/images/user/6.jpg differ
diff --git a/tests/fixtures/images/user/7.jpg b/tests/fixtures/images/user/7.jpg
new file mode 100644
index 0000000..70d3eeb
Binary files /dev/null and b/tests/fixtures/images/user/7.jpg differ
diff --git a/tests/fixtures/images/user/8.jpg b/tests/fixtures/images/user/8.jpg
new file mode 100644
index 0000000..82df15f
Binary files /dev/null and b/tests/fixtures/images/user/8.jpg differ
diff --git a/tests/fixtures/images/user/9.jpg b/tests/fixtures/images/user/9.jpg
new file mode 100644
index 0000000..0c61fbc
Binary files /dev/null and b/tests/fixtures/images/user/9.jpg differ
diff --git a/tests/fixtures/images/user/README.md b/tests/fixtures/images/user/README.md
new file mode 100644
index 0000000..ecd40c8
--- /dev/null
+++ b/tests/fixtures/images/user/README.md
@@ -0,0 +1,4 @@
+# User Images
+
+This is used when creating users with images. If you don't do that, feel free to
+delete this directory.
diff --git a/tests/fixtures/images/user/kody.png b/tests/fixtures/images/user/kody.png
new file mode 100644
index 0000000..a10de95
Binary files /dev/null and b/tests/fixtures/images/user/kody.png differ
diff --git a/tests/mocks/README.md b/tests/mocks/README.md
new file mode 100644
index 0000000..b4c3011
--- /dev/null
+++ b/tests/mocks/README.md
@@ -0,0 +1,9 @@
+# Mocks
+
+Use this to mock any third party HTTP resources that you don't have running
+locally and want to have mocked for local development as well as tests.
+
+Learn more about how to use this at [mswjs.io](https://mswjs.io/)
+
+For an extensive example, see the
+[source code for kentcdodds.com](https://github.com/kentcdodds/kentcdodds.com/blob/main/mocks/index.ts)
diff --git a/tests/mocks/github.ts b/tests/mocks/github.ts
new file mode 100644
index 0000000..3ada535
--- /dev/null
+++ b/tests/mocks/github.ts
@@ -0,0 +1,193 @@
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+import { faker } from '@faker-js/faker'
+import fsExtra from 'fs-extra'
+import { HttpResponse, passthrough, http, type HttpHandler } from 'msw'
+
+const { json } = HttpResponse
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const here = (...s: Array) => path.join(__dirname, ...s)
+
+const githubUserFixturePath = path.join(
+ here(
+ '..',
+ 'fixtures',
+ 'github',
+ `users.${process.env.VITEST_POOL_ID || 0}.local.json`,
+ ),
+)
+
+await fsExtra.ensureDir(path.dirname(githubUserFixturePath))
+
+function createGitHubUser(code?: string | null) {
+ const createEmail = () => ({
+ email: faker.internet.email(),
+ verified: faker.datatype.boolean(),
+ primary: false, // <-- can only have one of these
+ visibility: faker.helpers.arrayElement(['public', null]),
+ })
+ const primaryEmail = {
+ ...createEmail(),
+ verified: true,
+ primary: true,
+ }
+
+ const emails = [
+ {
+ email: faker.internet.email(),
+ verified: false,
+ primary: false,
+ visibility: 'public',
+ },
+ {
+ email: faker.internet.email(),
+ verified: true,
+ primary: false,
+ visibility: null,
+ },
+ primaryEmail,
+ ]
+
+ code ??= faker.string.uuid()
+ return {
+ code,
+ accessToken: `${code}_mock_access_token`,
+ profile: {
+ login: faker.internet.userName(),
+ id: faker.string.uuid(),
+ name: faker.person.fullName(),
+ avatar_url: 'https://github.com/ghost.png',
+ emails: emails.map((e) => e.email),
+ },
+ emails,
+ primaryEmail: primaryEmail.email,
+ }
+}
+
+export type GitHubUser = ReturnType
+
+async function getGitHubUsers() {
+ try {
+ if (await fsExtra.pathExists(githubUserFixturePath)) {
+ const json = await fsExtra.readJson(githubUserFixturePath)
+ return json as Array
+ }
+ return []
+ } catch (error) {
+ console.error(error)
+ return []
+ }
+}
+
+export async function deleteGitHubUser(primaryEmail: string) {
+ const users = await getGitHubUsers()
+ const user = users.find((u) => u.primaryEmail === primaryEmail)
+ if (!user) return null
+ await setGitHubUsers(users.filter((u) => u.primaryEmail !== primaryEmail))
+ return user
+}
+
+export async function deleteGitHubUsers() {
+ await fsExtra.remove(githubUserFixturePath)
+}
+
+async function setGitHubUsers(users: Array) {
+ await fsExtra.writeJson(githubUserFixturePath, users, { spaces: 2 })
+}
+
+export async function insertGitHubUser(code?: string | null) {
+ const githubUsers = await getGitHubUsers()
+ let user = githubUsers.find((u) => u.code === code)
+ if (user) {
+ Object.assign(user, createGitHubUser(code))
+ } else {
+ user = createGitHubUser(code)
+ githubUsers.push(user)
+ }
+ await setGitHubUsers(githubUsers)
+ return user
+}
+
+async function getUser(request: Request) {
+ const accessToken = request.headers
+ .get('authorization')
+ ?.slice('token '.length)
+
+ if (!accessToken) {
+ return new Response('Unauthorized', { status: 401 })
+ }
+ const user = (await getGitHubUsers()).find(
+ (u) => u.accessToken === accessToken,
+ )
+
+ if (!user) {
+ return new Response('Not Found', { status: 404 })
+ }
+ return user
+}
+
+const passthroughGitHub =
+ !process.env.GITHUB_CLIENT_ID.startsWith('MOCK_') &&
+ process.env.NODE_ENV !== 'test'
+
+export const handlers: Array = [
+ http.post(
+ 'https://github.com/login/oauth/access_token',
+ async ({ request }) => {
+ if (passthroughGitHub) return passthrough()
+ const params = new URLSearchParams(await request.text())
+
+ const code = params.get('code')
+ const githubUsers = await getGitHubUsers()
+ let user = githubUsers.find((u) => u.code === code)
+ if (!user) {
+ user = await insertGitHubUser(code)
+ }
+
+ return new Response(
+ new URLSearchParams({
+ access_token: user.accessToken,
+ token_type: '__MOCK_TOKEN_TYPE__',
+ }).toString(),
+ { headers: { 'content-type': 'application/x-www-form-urlencoded' } },
+ )
+ },
+ ),
+ http.get('https://api.github.com/user/emails', async ({ request }) => {
+ if (passthroughGitHub) return passthrough()
+
+ const user = await getUser(request)
+ if (user instanceof Response) return user
+
+ return json(user.emails)
+ }),
+ http.get('https://api.github.com/user/:id', async ({ params }) => {
+ if (passthroughGitHub) return passthrough()
+
+ const mockUser = (await getGitHubUsers()).find(
+ (u) => u.profile.id === params.id,
+ )
+ if (mockUser) return json(mockUser.profile)
+
+ return new Response('Not Found', { status: 404 })
+ }),
+ http.get('https://api.github.com/user', async ({ request }) => {
+ if (passthroughGitHub) return passthrough()
+
+ const user = await getUser(request)
+ if (user instanceof Response) return user
+
+ return json(user.profile)
+ }),
+ http.get('https://github.com/ghost.png', async () => {
+ if (passthroughGitHub) return passthrough()
+
+ const buffer = await fsExtra.readFile('./tests/fixtures/github/ghost.jpg')
+ return new Response(buffer, {
+ // the .png is not a mistake even though it looks like it... It's really a jpg
+ // but the ghost image URL really has a png extension đ
+ headers: { 'content-type': 'image/jpg' },
+ })
+ }),
+]
diff --git a/tests/mocks/index.ts b/tests/mocks/index.ts
new file mode 100644
index 0000000..58a56ab
--- /dev/null
+++ b/tests/mocks/index.ts
@@ -0,0 +1,29 @@
+import closeWithGrace from 'close-with-grace'
+import { setupServer } from 'msw/node'
+import { handlers as githubHandlers } from './github.ts'
+import { handlers as resendHandlers } from './resend.ts'
+
+export const server = setupServer(...resendHandlers, ...githubHandlers)
+
+server.listen({
+ onUnhandledRequest(request, print) {
+ // Do not print warnings on unhandled requests to https://<:userId>.ingest.us.sentry.io/api/
+ // Note: a request handler with passthrough is not suited with this type of url
+ // until there is a more permissible url catching system
+ // like requested at https://github.com/mswjs/msw/issues/1804
+ if (request.url.includes('.sentry.io')) {
+ return
+ }
+
+ // Print the regular MSW unhandled request warning otherwise.
+ print.warning()
+ },
+})
+
+if (process.env.NODE_ENV !== 'test') {
+ console.info('đś Mock server installed')
+
+ closeWithGrace(() => {
+ server.close()
+ })
+}
diff --git a/tests/mocks/resend.ts b/tests/mocks/resend.ts
new file mode 100644
index 0000000..7e7c424
--- /dev/null
+++ b/tests/mocks/resend.ts
@@ -0,0 +1,22 @@
+import { faker } from '@faker-js/faker'
+import { HttpResponse, http, type HttpHandler } from 'msw'
+import { requireHeader, writeEmail } from './utils.ts'
+
+const { json } = HttpResponse
+
+export const handlers: Array = [
+ http.post(`https://api.resend.com/emails`, async ({ request }) => {
+ requireHeader(request.headers, 'Authorization')
+ const body = await request.json()
+ console.info('đś mocked email contents:', body)
+
+ const email = await writeEmail(body)
+
+ return json({
+ id: faker.string.uuid(),
+ from: email.from,
+ to: email.to,
+ created_at: new Date().toISOString(),
+ })
+ }),
+]
diff --git a/tests/mocks/utils.ts b/tests/mocks/utils.ts
new file mode 100644
index 0000000..0d31af7
--- /dev/null
+++ b/tests/mocks/utils.ts
@@ -0,0 +1,65 @@
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+import fsExtra from 'fs-extra'
+import { z } from 'zod'
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const fixturesDirPath = path.join(__dirname, '..', 'fixtures')
+
+export async function readFixture(subdir: string, name: string) {
+ return fsExtra.readJSON(path.join(fixturesDirPath, subdir, `${name}.json`))
+}
+
+export async function createFixture(
+ subdir: string,
+ name: string,
+ data: unknown,
+) {
+ const dir = path.join(fixturesDirPath, subdir)
+ await fsExtra.ensureDir(dir)
+ return fsExtra.writeJSON(path.join(dir, `./${name}.json`), data)
+}
+
+export const EmailSchema = z.object({
+ to: z.string(),
+ from: z.string(),
+ subject: z.string(),
+ text: z.string(),
+ html: z.string(),
+})
+
+export async function writeEmail(rawEmail: unknown) {
+ const email = EmailSchema.parse(rawEmail)
+ await createFixture('email', email.to, email)
+ return email
+}
+
+export async function requireEmail(recipient: string) {
+ const email = await readEmail(recipient)
+ if (!email) throw new Error(`Email to ${recipient} not found`)
+ return email
+}
+
+export async function readEmail(recipient: string) {
+ try {
+ const email = await readFixture('email', recipient)
+ return EmailSchema.parse(email)
+ } catch (error) {
+ console.error(`Error reading email`, error)
+ return null
+ }
+}
+
+export function requireHeader(headers: Headers, header: string) {
+ if (!headers.has(header)) {
+ const headersString = JSON.stringify(
+ Object.fromEntries(headers.entries()),
+ null,
+ 2,
+ )
+ throw new Error(
+ `Header "${header}" required, but not found in ${headersString}`,
+ )
+ }
+ return headers.get(header)
+}
diff --git a/tests/playwright-utils.ts b/tests/playwright-utils.ts
new file mode 100644
index 0000000..a27c02c
--- /dev/null
+++ b/tests/playwright-utils.ts
@@ -0,0 +1,162 @@
+import { test as base } from '@playwright/test'
+import { type User as UserModel } from '@prisma/client'
+import * as setCookieParser from 'set-cookie-parser'
+import {
+ getPasswordHash,
+ getSessionExpirationDate,
+ sessionKey,
+} from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { MOCK_CODE_GITHUB_HEADER } from '#app/utils/providers/constants.js'
+import { normalizeEmail } from '#app/utils/providers/provider.js'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import { createUser } from './db-utils.ts'
+import {
+ type GitHubUser,
+ deleteGitHubUser,
+ insertGitHubUser,
+} from './mocks/github.ts'
+
+export * from './db-utils.ts'
+
+type GetOrInsertUserOptions = {
+ id?: string
+ username?: UserModel['username']
+ password?: string
+ email?: UserModel['email']
+}
+
+type User = {
+ id: string
+ email: string
+ username: string
+ name: string | null
+}
+
+async function getOrInsertUser({
+ id,
+ username,
+ password,
+ email,
+}: GetOrInsertUserOptions = {}): Promise {
+ const select = { id: true, email: true, username: true, name: true }
+ if (id) {
+ return await prisma.user.findUniqueOrThrow({
+ select,
+ where: { id: id },
+ })
+ } else {
+ const userData = createUser()
+ username ??= userData.username
+ password ??= userData.username
+ email ??= userData.email
+ return await prisma.user.create({
+ select,
+ data: {
+ ...userData,
+ email,
+ username,
+ roles: { connect: { name: 'user' } },
+ password: { create: { hash: await getPasswordHash(password) } },
+ },
+ })
+ }
+}
+
+export const test = base.extend<{
+ insertNewUser(options?: GetOrInsertUserOptions): Promise
+ login(options?: GetOrInsertUserOptions): Promise
+ prepareGitHubUser(): Promise
+}>({
+ insertNewUser: async ({}, use) => {
+ let userId: string | undefined = undefined
+ await use(async (options) => {
+ const user = await getOrInsertUser(options)
+ userId = user.id
+ return user
+ })
+ await prisma.user.delete({ where: { id: userId } }).catch(() => {})
+ },
+ login: async ({ page }, use) => {
+ let userId: string | undefined = undefined
+ await use(async (options) => {
+ const user = await getOrInsertUser(options)
+ userId = user.id
+ const session = await prisma.session.create({
+ data: {
+ expirationDate: getSessionExpirationDate(),
+ userId: user.id,
+ },
+ select: { id: true },
+ })
+
+ const authSession = await authSessionStorage.getSession()
+ authSession.set(sessionKey, session.id)
+ const cookieConfig = setCookieParser.parseString(
+ await authSessionStorage.commitSession(authSession),
+ )
+ const newConfig = {
+ ...cookieConfig,
+ domain: 'localhost',
+ expires: cookieConfig.expires?.getTime(),
+ sameSite: cookieConfig.sameSite as 'Strict' | 'Lax' | 'None',
+ }
+ await page.context().addCookies([newConfig])
+ return user
+ })
+ await prisma.user.deleteMany({ where: { id: userId } })
+ },
+ prepareGitHubUser: async ({ page }, use, testInfo) => {
+ await page.route(/\/auth\/github(?!\/callback)/, async (route, request) => {
+ const headers = {
+ ...request.headers(),
+ [MOCK_CODE_GITHUB_HEADER]: testInfo.testId,
+ }
+ await route.continue({ headers })
+ })
+
+ let ghUser: GitHubUser | null = null
+ await use(async () => {
+ const newGitHubUser = await insertGitHubUser(testInfo.testId)!
+ ghUser = newGitHubUser
+ return newGitHubUser
+ })
+
+ const user = await prisma.user.findUniqueOrThrow({
+ select: { id: true, name: true },
+ where: { email: normalizeEmail(ghUser!.primaryEmail) },
+ })
+ await prisma.user.delete({ where: { id: user.id } })
+ await prisma.session.deleteMany({ where: { userId: user.id } })
+ await deleteGitHubUser(ghUser!.primaryEmail)
+ },
+})
+export const { expect } = test
+
+/**
+ * This allows you to wait for something (like an email to be available).
+ *
+ * It calls the callback every 50ms until it returns a value (and does not throw
+ * an error). After the timeout, it will throw the last error that was thrown or
+ * throw the error message provided as a fallback
+ */
+export async function waitFor(
+ cb: () => ReturnValue | Promise,
+ {
+ errorMessage,
+ timeout = 5000,
+ }: { errorMessage?: string; timeout?: number } = {},
+) {
+ const endTime = Date.now() + timeout
+ let lastError: unknown = new Error(errorMessage)
+ while (Date.now() < endTime) {
+ try {
+ const response = await cb()
+ if (response) return response
+ } catch (e: unknown) {
+ lastError = e
+ }
+ await new Promise((r) => setTimeout(r, 100))
+ }
+ throw lastError
+}
diff --git a/tests/setup/custom-matchers.ts b/tests/setup/custom-matchers.ts
new file mode 100644
index 0000000..82017ad
--- /dev/null
+++ b/tests/setup/custom-matchers.ts
@@ -0,0 +1,166 @@
+import * as setCookieParser from 'set-cookie-parser'
+import { expect } from 'vitest'
+import { sessionKey } from '#app/utils/auth.server.ts'
+import { prisma } from '#app/utils/db.server.ts'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+import {
+ type ToastInput,
+ toastSessionStorage,
+ toastKey,
+} from '#app/utils/toast.server.ts'
+import { convertSetCookieToCookie } from '#tests/utils.ts'
+
+import '@testing-library/jest-dom/vitest'
+
+expect.extend({
+ toHaveRedirect(response: Response, redirectTo?: string) {
+ const location = response.headers.get('location')
+ const redirectToSupplied = redirectTo !== undefined
+ if (redirectToSupplied !== Boolean(location)) {
+ return {
+ pass: Boolean(location),
+ message: () =>
+ `Expected response to ${this.isNot ? 'not ' : ''}redirect${
+ redirectToSupplied
+ ? ` to ${this.utils.printExpected(redirectTo)}`
+ : ''
+ } but got ${
+ location ? 'no redirect' : this.utils.printReceived(location)
+ }`,
+ }
+ }
+ const isRedirectStatusCode = response.status >= 300 && response.status < 400
+ if (!isRedirectStatusCode) {
+ return {
+ pass: false,
+ message: () =>
+ `Expected redirect to ${
+ this.isNot ? 'not ' : ''
+ }be ${this.utils.printExpected(
+ '>= 300 && < 400',
+ )} but got ${this.utils.printReceived(response.status)}`,
+ }
+ }
+
+ function toUrl(s?: string | null) {
+ s ??= ''
+ return s.startsWith('http')
+ ? new URL(s)
+ : new URL(s, 'https://example.com')
+ }
+
+ function urlsMatch(u1: URL, u2: URL) {
+ const u1SP = new URL(u1).searchParams
+ u1SP.sort()
+ const u2SP = new URL(u2).searchParams
+ u2SP.sort()
+ return (
+ u1.origin === u2.origin &&
+ u1.pathname === u2.pathname &&
+ u1SP.toString() === u2SP.toString() &&
+ u1.hash === u2.hash
+ )
+ }
+
+ return {
+ pass:
+ location == redirectTo || urlsMatch(toUrl(location), toUrl(redirectTo)),
+ message: () =>
+ `Expected response to ${
+ this.isNot ? 'not ' : ''
+ }redirect to ${this.utils.printExpected(
+ redirectTo,
+ )} but got ${this.utils.printReceived(location)}`,
+ }
+ },
+ async toHaveSessionForUser(response: Response, userId: string) {
+ const setCookies = response.headers.getSetCookie()
+ const sessionSetCookie = setCookies.find(
+ (c) => setCookieParser.parseString(c).name === 'en_session',
+ )
+
+ if (!sessionSetCookie) {
+ return {
+ pass: false,
+ message: () =>
+ `The en_session set-cookie header was${
+ this.isNot ? '' : ' not'
+ } defined`,
+ }
+ }
+
+ const authSession = await authSessionStorage.getSession(
+ convertSetCookieToCookie(sessionSetCookie),
+ )
+ const sessionValue = authSession.get(sessionKey)
+
+ if (!sessionValue) {
+ return {
+ pass: false,
+ message: () => `A session was${this.isNot ? '' : ' not'} set in cookie`,
+ }
+ }
+
+ const session = await prisma.session.findUnique({
+ select: { id: true },
+ where: { userId, id: sessionValue },
+ })
+
+ return {
+ pass: Boolean(session),
+ message: () =>
+ `A session was${
+ this.isNot ? ' not' : ''
+ } created in the database for ${userId}`,
+ }
+ },
+ async toSendToast(response: Response, toast: ToastInput) {
+ const setCookies = response.headers.getSetCookie()
+ const toastSetCookie = setCookies.find(
+ (c) => setCookieParser.parseString(c).name === 'en_toast',
+ )
+
+ if (!toastSetCookie) {
+ return {
+ pass: false,
+ message: () =>
+ `en_toast set-cookie header was${this.isNot ? '' : ' not'} defined`,
+ }
+ }
+
+ const toastSession = await toastSessionStorage.getSession(
+ convertSetCookieToCookie(toastSetCookie),
+ )
+ const toastValue = toastSession.get(toastKey)
+
+ if (!toastValue) {
+ return {
+ pass: false,
+ message: () => `toast was${this.isNot ? '' : ' not'} set in session`,
+ }
+ }
+
+ const pass = this.equals(toastValue, toast)
+
+ const diff = pass ? null : `\n${this.utils.diff(toastValue, toast)}`
+
+ return {
+ pass,
+ message: () =>
+ `toast in the response ${
+ this.isNot ? 'does not match' : 'matches'
+ } the expected toast${diff}`,
+ }
+ },
+})
+
+interface CustomMatchers {
+ toHaveRedirect(redirectTo: string | null): R
+ toHaveSessionForUser(userId: string): Promise
+ toSendToast(toast: ToastInput): Promise
+}
+
+declare module 'vitest' {
+ interface Assertion extends CustomMatchers {}
+ interface AsymmetricMatchersContaining extends CustomMatchers {}
+}
diff --git a/tests/setup/db-setup.ts b/tests/setup/db-setup.ts
new file mode 100644
index 0000000..2cbc646
--- /dev/null
+++ b/tests/setup/db-setup.ts
@@ -0,0 +1,20 @@
+import path from 'node:path'
+import fsExtra from 'fs-extra'
+import { afterAll, beforeEach } from 'vitest'
+import { BASE_DATABASE_PATH } from './global-setup.ts'
+
+const databaseFile = `./tests/prisma/data.${process.env.VITEST_POOL_ID || 0}.db`
+const databasePath = path.join(process.cwd(), databaseFile)
+process.env.DATABASE_URL = `file:${databasePath}`
+
+beforeEach(async () => {
+ await fsExtra.copyFile(BASE_DATABASE_PATH, databasePath)
+})
+
+afterAll(async () => {
+ // we *must* use dynamic imports here so the process.env.DATABASE_URL is set
+ // before prisma is imported and initialized
+ const { prisma } = await import('#app/utils/db.server.ts')
+ await prisma.$disconnect()
+ await fsExtra.remove(databasePath)
+})
diff --git a/tests/setup/global-setup.ts b/tests/setup/global-setup.ts
new file mode 100644
index 0000000..af7fe31
--- /dev/null
+++ b/tests/setup/global-setup.ts
@@ -0,0 +1,35 @@
+import path from 'node:path'
+import { execaCommand } from 'execa'
+import fsExtra from 'fs-extra'
+
+export const BASE_DATABASE_PATH = path.join(
+ process.cwd(),
+ `./tests/prisma/base.db`,
+)
+
+export async function setup() {
+ const databaseExists = await fsExtra.pathExists(BASE_DATABASE_PATH)
+
+ if (databaseExists) {
+ const databaseLastModifiedAt = (await fsExtra.stat(BASE_DATABASE_PATH))
+ .mtime
+ const prismaSchemaLastModifiedAt = (
+ await fsExtra.stat('./prisma/schema.prisma')
+ ).mtime
+
+ if (prismaSchemaLastModifiedAt < databaseLastModifiedAt) {
+ return
+ }
+ }
+
+ await execaCommand(
+ 'npx prisma migrate reset --force --skip-seed --skip-generate',
+ {
+ stdio: 'inherit',
+ env: {
+ ...process.env,
+ DATABASE_URL: `file:${BASE_DATABASE_PATH}`,
+ },
+ },
+ )
+}
diff --git a/tests/setup/setup-test-env.ts b/tests/setup/setup-test-env.ts
new file mode 100644
index 0000000..18e2066
--- /dev/null
+++ b/tests/setup/setup-test-env.ts
@@ -0,0 +1,27 @@
+import 'dotenv/config'
+import './db-setup.ts'
+import '#app/utils/env.server.ts'
+// we need these to be imported first đ
+
+import { cleanup } from '@testing-library/react'
+import { afterEach, beforeEach, vi, type MockInstance } from 'vitest'
+import { server } from '#tests/mocks/index.ts'
+import './custom-matchers.ts'
+
+afterEach(() => server.resetHandlers())
+afterEach(() => cleanup())
+
+export let consoleError: MockInstance<(typeof console)['error']>
+
+beforeEach(() => {
+ const originalConsoleError = console.error
+ consoleError = vi.spyOn(console, 'error')
+ consoleError.mockImplementation(
+ (...args: Parameters) => {
+ originalConsoleError(...args)
+ throw new Error(
+ 'Console error was called. Call consoleError.mockImplementation(() => {}) if this is expected.',
+ )
+ },
+ )
+})
diff --git a/tests/utils.ts b/tests/utils.ts
new file mode 100644
index 0000000..b39457d
--- /dev/null
+++ b/tests/utils.ts
@@ -0,0 +1,33 @@
+import * as setCookieParser from 'set-cookie-parser'
+import { sessionKey } from '#app/utils/auth.server.ts'
+import { authSessionStorage } from '#app/utils/session.server.ts'
+
+export const BASE_URL = 'https://www.epicstack.dev'
+
+export function convertSetCookieToCookie(setCookie: string) {
+ const parsedCookie = setCookieParser.parseString(setCookie)
+ return new URLSearchParams({
+ [parsedCookie.name]: parsedCookie.value,
+ }).toString()
+}
+
+export async function getSessionSetCookieHeader(
+ session: { id: string },
+ existingCookie?: string,
+) {
+ const authSession = await authSessionStorage.getSession(existingCookie)
+ authSession.set(sessionKey, session.id)
+ const setCookieHeader = await authSessionStorage.commitSession(authSession)
+ return setCookieHeader
+}
+
+export async function getSessionCookieHeader(
+ session: { id: string },
+ existingCookie?: string,
+) {
+ const setCookieHeader = await getSessionSetCookieHeader(
+ session,
+ existingCookie,
+ )
+ return convertSetCookieToCookie(setCookieHeader)
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..523f576
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "include": ["**/*.ts", "**/*.tsx"],
+ "extends": ["@epic-web/config/typescript"],
+ "compilerOptions": {
+ "paths": {
+ "#app/*": ["./app/*"],
+ "#tests/*": ["./tests/*"],
+ "@/icon-name": [
+ "./app/components/ui/icons/name.d.ts",
+ "./types/icon-name.d.ts"
+ ]
+ }
+ }
+}
diff --git a/types/deps.d.ts b/types/deps.d.ts
new file mode 100644
index 0000000..121be70
--- /dev/null
+++ b/types/deps.d.ts
@@ -0,0 +1,6 @@
+// This module should contain type definitions for modules which do not have
+// their own type definitions and are not available on DefinitelyTyped.
+
+// declare module 'some-untyped-pkg' {
+// export function foo(): void;
+// }
diff --git a/types/env.env.d.ts b/types/env.env.d.ts
new file mode 100644
index 0000000..8d2f951
--- /dev/null
+++ b/types/env.env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/types/icon-name.d.ts b/types/icon-name.d.ts
new file mode 100644
index 0000000..6f47700
--- /dev/null
+++ b/types/icon-name.d.ts
@@ -0,0 +1,3 @@
+// This file is a fallback until you run npm run build:icons
+
+export type IconName = string
diff --git a/types/reset.d.ts b/types/reset.d.ts
new file mode 100644
index 0000000..3b8ad67
--- /dev/null
+++ b/types/reset.d.ts
@@ -0,0 +1,2 @@
+// Do not add any other lines of code to this file!
+import '@total-typescript/ts-reset/dom'
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..242db83
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,93 @@
+import { vitePlugin as remix } from '@remix-run/dev'
+import { sentryVitePlugin } from '@sentry/vite-plugin'
+import { glob } from 'glob'
+import { flatRoutes } from 'remix-flat-routes'
+import { defineConfig } from 'vite'
+import { envOnlyMacros } from 'vite-env-only'
+
+const MODE = process.env.NODE_ENV
+
+export default defineConfig({
+ build: {
+ cssMinify: MODE === 'production',
+
+ rollupOptions: {
+ external: [/node:.*/, 'fsevents'],
+ },
+
+ assetsInlineLimit: (source: string) => {
+ if (
+ source.endsWith('sprite.svg') ||
+ source.endsWith('favicon.svg') ||
+ source.endsWith('apple-touch-icon.png')
+ ) {
+ return false
+ }
+ },
+
+ sourcemap: true,
+ },
+ server: {
+ watch: {
+ ignored: ['**/playwright-report/**'],
+ },
+ },
+ plugins: [
+ envOnlyMacros(),
+ // it would be really nice to have this enabled in tests, but we'll have to
+ // wait until https://github.com/remix-run/remix/issues/9871 is fixed
+ process.env.NODE_ENV === 'test'
+ ? null
+ : remix({
+ ignoredRouteFiles: ['**/*'],
+ serverModuleFormat: 'esm',
+ routes: async (defineRoutes) => {
+ return flatRoutes('routes', defineRoutes, {
+ ignoredRouteFiles: [
+ '.*',
+ '**/*.css',
+ '**/*.test.{js,jsx,ts,tsx}',
+ '**/__*.*',
+ // This is for server-side utilities you want to colocate
+ // next to your routes without making an additional
+ // directory. If you need a route that includes "server" or
+ // "client" in the filename, use the escape brackets like:
+ // my-route.[server].tsx
+ '**/*.server.*',
+ '**/*.client.*',
+ ],
+ })
+ },
+ }),
+ process.env.SENTRY_AUTH_TOKEN
+ ? sentryVitePlugin({
+ disable: MODE !== 'production',
+ authToken: process.env.SENTRY_AUTH_TOKEN,
+ org: process.env.SENTRY_ORG,
+ project: process.env.SENTRY_PROJECT,
+ release: {
+ name: process.env.COMMIT_SHA,
+ setCommits: {
+ auto: true,
+ },
+ },
+ sourcemaps: {
+ filesToDeleteAfterUpload: await glob([
+ './build/**/*.map',
+ '.server-build/**/*.map',
+ ]),
+ },
+ })
+ : null,
+ ],
+ test: {
+ include: ['./app/**/*.test.{ts,tsx}'],
+ setupFiles: ['./tests/setup/setup-test-env.ts'],
+ globalSetup: ['./tests/setup/global-setup.ts'],
+ restoreMocks: true,
+ coverage: {
+ include: ['app/**/*.{ts,tsx}'],
+ all: true,
+ },
+ },
+})