Compare commits
14 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a455a71150 | ||
|
|
8f96736328 | ||
|
|
735c6c64eb | ||
|
|
64d1b58b27 | ||
|
|
f785b33068 | ||
|
|
3f83ee6dc1 | ||
|
|
060d76d5fe | ||
|
|
40bf33a9e5 | ||
|
|
0f95f330ef | ||
|
|
9f889983dd | ||
|
|
0d21abd3a0 | ||
|
|
8270c53509 | ||
|
|
8006d523c7 | ||
|
|
7891c0b4b7 |
67 changed files with 1635 additions and 461 deletions
26
.env
26
.env
|
|
@ -1,13 +1,25 @@
|
|||
NODE_ENV=
|
||||
NPM_TOKEN=
|
||||
|
||||
# TWILIO
|
||||
TWILIO_ACCOUNT_SID=
|
||||
TWILIO_AUTH_TOKEN=
|
||||
TWILIO_PHONE_NUMBER=
|
||||
##########################
|
||||
# APP VARIABLES #
|
||||
##########################
|
||||
APP_NAME=hestia
|
||||
|
||||
# PRISMA
|
||||
##########################
|
||||
# SECRETS #
|
||||
##########################
|
||||
SECRETS_PASSWORD=secret_do_not_commit_or_change_this_create_.env.local_instead
|
||||
SECRETS_SALT=secret_do_not_commit_or_change_this_create_.env.local_instead
|
||||
SECRETS_IV_POSITION=secret_do_not_commit_or_change_this_create_.env.local_instead
|
||||
|
||||
##########################
|
||||
# DATABASE #
|
||||
##########################
|
||||
DATABASE_URL="postgres://hestia:test123@localhost:5432/hestia"
|
||||
DIRECT_URL="postgres://hestia:test123@localhost:5432/hestia"
|
||||
|
||||
# CLERK
|
||||
##########################
|
||||
# AUTHENTICATION #
|
||||
##########################
|
||||
PUBLIC_CLERK_PUBLISHABLE_KEY=secret_do_not_commit_or_change_this_create_.env.local_instead
|
||||
CLERK_SECRET_KEY=secret_do_not_commit_or_change_this_create_.env.local_instead
|
||||
72
.github/workflows/deploy.yml
vendored
72
.github/workflows/deploy.yml
vendored
|
|
@ -1,58 +1,46 @@
|
|||
name: Deployment
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
jobs:
|
||||
setup:
|
||||
name: Setup
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
cache-key: ${{ steps.cache-restore.outputs.cache-primary-key }}
|
||||
deploy-app:
|
||||
name: Deploy App
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Bun Setup
|
||||
uses: oven-sh/setup-bun@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
bun-version-file: '.tool-versions'
|
||||
- name: Restore node_modules
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-restore
|
||||
registry: ${{ env.GITHUB_SERVER_URL }}
|
||||
username: ${{ env.GITHUB_REPOSITORY_OWNER }}
|
||||
password: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bun
|
||||
- name: Install
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
run: bun install
|
||||
- name: Cache node_modules
|
||||
if: steps.cache-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
id: cache-save
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
|
||||
storybook:
|
||||
push: true
|
||||
tags: git.palko.ca/${{ env.GITHUB_REPOSITORY }}:latest
|
||||
deploy-storybook:
|
||||
name: Deploy Storybook
|
||||
needs: [setup]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Bun Setup
|
||||
uses: oven-sh/setup-bun@v2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
bun-version-file: '.tool-versions'
|
||||
- name: Restore node_modules
|
||||
uses: actions/cache/restore@v4
|
||||
id: cache-restore
|
||||
registry: ${{ env.GITHUB_SERVER_URL }}
|
||||
username: ${{ env.GITHUB_REPOSITORY_OWNER }}
|
||||
password: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
|
||||
- name: Build Storybook
|
||||
run: bun build-storybook
|
||||
push: true
|
||||
file: Dockerfile.storybook
|
||||
tags: git.palko.ca/${{ env.GITHUB_REPOSITORY }}-storybook:latest
|
||||
|
|
|
|||
16
.github/workflows/pr.yaml
vendored
16
.github/workflows/pr.yaml
vendored
|
|
@ -1,7 +1,17 @@
|
|||
name: PR Gate
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ['*']
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
checks:
|
||||
name: Checks
|
||||
|
|
@ -17,11 +27,11 @@ jobs:
|
|||
run: bun install
|
||||
- name: Lint
|
||||
run: bun lint
|
||||
- name: Test
|
||||
run: bun test
|
||||
- name: Build
|
||||
run: bun run build
|
||||
- name: Svelte Check
|
||||
run: bun check
|
||||
- name: Prisma Check
|
||||
run: bun prisma:validate
|
||||
- name: Test
|
||||
run: bun run test:unit
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -14,6 +14,9 @@ node_modules
|
|||
Thumbs.db
|
||||
.idea
|
||||
|
||||
# Storybook
|
||||
storybook-static
|
||||
|
||||
# Vite
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@
|
|||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
yarn.lock
|
||||
*.md
|
||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
FROM oven/bun:1.2-alpine AS build
|
||||
|
||||
WORKDIR /opt/build
|
||||
|
||||
COPY . .
|
||||
RUN bun install --frozen-lockfile \
|
||||
&& bun run build
|
||||
|
||||
FROM node:18-alpine3.21
|
||||
|
||||
WORKDIR /opt/app
|
||||
|
||||
COPY ./package.json ./package.json
|
||||
COPY --from=build --chown=1000:1000 /opt/build/node_modules/ /opt/app/node_modules/
|
||||
COPY --from=build --chown=1000:1000 /opt/build/build /opt/app
|
||||
|
||||
ENTRYPOINT [ "node", "index.js" ]
|
||||
11
Dockerfile.storybook
Normal file
11
Dockerfile.storybook
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
FROM oven/bun:1.2-alpine AS build
|
||||
|
||||
WORKDIR /opt/build
|
||||
|
||||
COPY . .
|
||||
RUN bun install --frozen-lockfile \
|
||||
&& bun run build-storybook
|
||||
|
||||
FROM nginx:alpine3.21
|
||||
|
||||
COPY --from=build --chown=1000:1000 /opt/build/storybook-static /usr/share/nginx/html
|
||||
16
README.md
16
README.md
|
|
@ -1,12 +1,16 @@
|
|||
# Hestia
|
||||
|
||||
Hestia is an early stage project
|
||||
<!--toc:start-->
|
||||
|
||||
- [Setup](#setup)
|
||||
- [Developing](#developing)
|
||||
- [Modifying Database Schema](#modifying-database-schema)
|
||||
- [Building](#building)
|
||||
- [Stack](#stack)
|
||||
- [Hestia](#hestia)
|
||||
- [Setup](#setup)
|
||||
- [Developing](#developing)
|
||||
- [Modifying Database Schema](#modifying-database-schema)
|
||||
- [Building](#building)
|
||||
- [Stack](#stack) - [Frontend](#frontend) - [Backend](#backend) - [Tools](#tools)
|
||||
<!--toc:end-->
|
||||
|
||||
Hestia is an early stage project
|
||||
|
||||
## Setup
|
||||
|
||||
|
|
|
|||
282
bun.lock
282
bun.lock
|
|
@ -9,7 +9,7 @@
|
|||
"@inlang/paraglide-sveltekit": "^0.15.0",
|
||||
"@pothos/core": "^4.3.0",
|
||||
"@pothos/plugin-prisma": "^4.4.0",
|
||||
"@prisma/client": "6.0.1",
|
||||
"@prisma/client": "6.3.1",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"clerk-sveltekit": "https://pkg.pr.new/wobsoriano/clerk-sveltekit@ca15d4e",
|
||||
"clsx": "^2.1.1",
|
||||
|
|
@ -28,19 +28,19 @@
|
|||
"@chromatic-com/storybook": "^3.2.2",
|
||||
"@eslint/compat": "^1.2.3",
|
||||
"@playwright/test": "^1.45.3",
|
||||
"@storybook/addon-essentials": "^8.4.7",
|
||||
"@storybook/addon-interactions": "^8.4.7",
|
||||
"@storybook/addon-essentials": "^8.5.0",
|
||||
"@storybook/addon-interactions": "^8.5.0",
|
||||
"@storybook/addon-styling-webpack": "^1.0.1",
|
||||
"@storybook/addon-svelte-csf": "^5.0.0-next.13",
|
||||
"@storybook/addon-themes": "^8.4.7",
|
||||
"@storybook/blocks": "^8.4.7",
|
||||
"@storybook/svelte": "^8.4.7",
|
||||
"@storybook/sveltekit": "^8.4.7",
|
||||
"@storybook/test": "^8.4.7",
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@storybook/addon-themes": "^8.5.0",
|
||||
"@storybook/blocks": "^8.5.0",
|
||||
"@storybook/svelte": "^8.5.0",
|
||||
"@storybook/sveltekit": "^8.5.0",
|
||||
"@storybook/test": "^8.5.0",
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/kit": "^2.15.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@types/bun": "^1.1.14",
|
||||
"@types/bun": "^1.1.15",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"daisyui": "^4.12.22",
|
||||
"eslint": "^9.7.0",
|
||||
|
|
@ -52,8 +52,8 @@
|
|||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"prisma": "^6.0.1",
|
||||
"storybook": "^8.4.7",
|
||||
"prisma": "6.3.1",
|
||||
"storybook": "^8.5.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwindcss": "^3.4.9",
|
||||
|
|
@ -75,17 +75,17 @@
|
|||
|
||||
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
|
||||
|
||||
"@babel/runtime": ["@babel/runtime@7.26.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw=="],
|
||||
"@babel/runtime": ["@babel/runtime@7.26.7", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ=="],
|
||||
|
||||
"@chromatic-com/storybook": ["@chromatic-com/storybook@3.2.3", "", { "dependencies": { "chromatic": "^11.15.0", "filesize": "^10.0.12", "jsonfile": "^6.1.0", "react-confetti": "^6.1.0", "strip-ansi": "^7.1.0" }, "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-3+hfANx79kIjP1qrOSLxpoAXOiYUA0S7A0WI0A24kASrv7USFNNW8etR5TjUilMb0LmqKUn3wDwUK2h6aceQ9g=="],
|
||||
"@chromatic-com/storybook": ["@chromatic-com/storybook@3.2.4", "", { "dependencies": { "chromatic": "^11.15.0", "filesize": "^10.0.12", "jsonfile": "^6.1.0", "react-confetti": "^6.1.0", "strip-ansi": "^7.1.0" }, "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-5/bOOYxfwZ2BktXeqcCpOVAoR6UCoeART5t9FVy22hoo8F291zOuX4y3SDgm10B1GVU/ZTtJWPT2X9wZFlxYLg=="],
|
||||
|
||||
"@clerk/backend": ["@clerk/backend@1.21.4", "", { "dependencies": { "@clerk/shared": "^2.20.4", "@clerk/types": "^4.40.0", "cookie": "0.7.0", "snakecase-keys": "5.4.4", "tslib": "2.4.1" } }, "sha512-PHJzBJrTxBAvHwscXwUwpippT7nHhphgycVcFb3655Dq6q0nRdKfo5GlkDHscEKxLOdmppB/168nXsVwSWf86w=="],
|
||||
|
||||
"@clerk/shared": ["@clerk/shared@2.20.8", "", { "dependencies": { "@clerk/types": "^4.41.0", "dequal": "2.0.3", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", "std-env": "^3.7.0", "swr": "^2.2.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-I94MUUpEKi31KMiK2ZL6hsvNsgRuqqtZ+dQlE8zEUZKW+7hoeGimUQTKf7yr2zQ6XDhpGTt+63Cysx7kIny7yQ=="],
|
||||
"@clerk/shared": ["@clerk/shared@2.20.14", "", { "dependencies": { "@clerk/types": "^4.44.0", "dequal": "2.0.3", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", "std-env": "^3.7.0", "swr": "^2.2.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-cQ5cRYHHLmYYSFg6OLuNUHxM6W4r5rabKOupP2jlGLns8WMHfbxNiLf/9nPUbLKDjWKG2Ott/nRN9iZQwcyfew=="],
|
||||
|
||||
"@clerk/themes": ["@clerk/themes@2.2.7", "", { "dependencies": { "@clerk/types": "^4.41.0", "tslib": "2.4.1" } }, "sha512-LM1cOYtG7pbtYotpZnZfiL0pzug1tSYOixw90vzGLXy9354MvWOJ2Hq+7xVslbUheL/eAMouoHzRMtpMGk8rvw=="],
|
||||
"@clerk/themes": ["@clerk/themes@2.2.12", "", { "dependencies": { "@clerk/types": "^4.44.0", "tslib": "2.4.1" } }, "sha512-2KLihkWClEUc5ZkIzNU9cTcpWtzxAm2GZRCSI0KUKZA/0V6glhmnxSSk+AQXzO9GpbyQm+UDIOQQSvQ10hnnFQ=="],
|
||||
|
||||
"@clerk/types": ["@clerk/types@4.41.0", "", { "dependencies": { "csstype": "3.1.1" } }, "sha512-pSIDJ6WKmkPLAThzuXABFt/K581iLjsZSOU7e+hDdb1PRElKi11stMJruDU8UjLBNFksZUG5Cfkt0iGrVQmpXw=="],
|
||||
"@clerk/types": ["@clerk/types@4.44.0", "", { "dependencies": { "csstype": "3.1.1" } }, "sha512-L9UNS21sQ7OAgXKUWSMaZWayI/qmVM4DGvGCAlL0tpzbzdFU1nkxRaMOT3FkmWKSahIq4BI+vJHfMC1ki9uuGg=="],
|
||||
|
||||
"@envelop/core": ["@envelop/core@5.0.3", "", { "dependencies": { "@envelop/types": "5.0.0", "tslib": "^2.5.0" } }, "sha512-SE3JxL7odst8igN6x77QWyPpXKXz/Hs5o5Y27r+9Br6WHIhkW90lYYVITWIJQ/qYgn5PkpbaVgeFY9rgqQaZ/A=="],
|
||||
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
|
||||
"@eslint/eslintrc": ["@eslint/eslintrc@3.2.0", "", { "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" } }, "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w=="],
|
||||
|
||||
"@eslint/js": ["@eslint/js@9.18.0", "", {}, "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA=="],
|
||||
"@eslint/js": ["@eslint/js@9.19.0", "", {}, "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ=="],
|
||||
|
||||
"@eslint/object-schema": ["@eslint/object-schema@2.1.5", "", {}, "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ=="],
|
||||
|
||||
|
|
@ -301,7 +301,7 @@
|
|||
|
||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
"@playwright/test": ["@playwright/test@1.49.1", "", { "dependencies": { "playwright": "1.49.1" }, "bin": { "playwright": "cli.js" } }, "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g=="],
|
||||
"@playwright/test": ["@playwright/test@1.50.0", "", { "dependencies": { "playwright": "1.50.0" }, "bin": { "playwright": "cli.js" } }, "sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw=="],
|
||||
|
||||
"@polka/url": ["@polka/url@1.0.0-next.28", "", {}, "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw=="],
|
||||
|
||||
|
|
@ -309,133 +309,141 @@
|
|||
|
||||
"@pothos/plugin-prisma": ["@pothos/plugin-prisma@4.4.0", "", { "dependencies": { "@prisma/generator-helper": "^6.0.0" }, "peerDependencies": { "@pothos/core": "*", "@prisma/client": "*", "graphql": ">=16.6.0", "typescript": ">=4.7.2" }, "bin": { "prisma-pothos-types": "bin/generator.js" } }, "sha512-TlXJ8QVOihpPbJGGHwOv2MUFv61xHU2xgGyTVp7KWNLQ6hzP9RH3nSQY7H1pNLOYR5wK+RyREJcaswVNwtxuqw=="],
|
||||
|
||||
"@prisma/client": ["@prisma/client@6.0.1", "", { "peerDependencies": { "prisma": "*" }, "optionalPeers": ["prisma"] }, "sha512-60w7kL6bUxz7M6Gs/V+OWMhwy94FshpngVmOY05TmGD0Lhk+Ac0ZgtjlL6Wll9TD4G03t4Sq1wZekNVy+Xdlbg=="],
|
||||
"@prisma/client": ["@prisma/client@6.3.1", "", { "peerDependencies": { "prisma": "*", "typescript": ">=5.1.0" }, "optionalPeers": ["prisma", "typescript"] }, "sha512-ARAJaPs+eBkemdky/XU3cvGRl+mIPHCN2lCXsl5Vlb0E2gV+R6IN7aCI8CisRGszEZondwIsW9Iz8EJkTdykyA=="],
|
||||
|
||||
"@prisma/debug": ["@prisma/debug@6.2.1", "", {}, "sha512-0KItvt39CmQxWkEw6oW+RQMD6RZ43SJWgEUnzxN8VC9ixMysa7MzZCZf22LCK5DSooiLNf8vM3LHZm/I/Ni7bQ=="],
|
||||
"@prisma/debug": ["@prisma/debug@6.3.1", "", {}, "sha512-RrEBkd+HLZx+ydfmYT0jUj7wjLiS95wfTOSQ+8FQbvb6vHh5AeKfEPt/XUQ5+Buljj8hltEfOslEW57/wQIVeA=="],
|
||||
|
||||
"@prisma/engines": ["@prisma/engines@6.2.1", "", { "dependencies": { "@prisma/debug": "6.2.1", "@prisma/engines-version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", "@prisma/fetch-engine": "6.2.1", "@prisma/get-platform": "6.2.1" } }, "sha512-lTBNLJBCxVT9iP5I7Mn6GlwqAxTpS5qMERrhebkUhtXpGVkBNd/jHnNJBZQW4kGDCKaQg/r2vlJYkzOHnAb7ZQ=="],
|
||||
"@prisma/engines": ["@prisma/engines@6.3.1", "", { "dependencies": { "@prisma/debug": "6.3.1", "@prisma/engines-version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", "@prisma/fetch-engine": "6.3.1", "@prisma/get-platform": "6.3.1" } }, "sha512-sXdqEVLyGAJ5/iUoG/Ea5AdHMN71m6PzMBWRQnLmhhOejzqAaEr8rUd623ql6OJpED4s/U4vIn4dg1qkF7vGag=="],
|
||||
|
||||
"@prisma/engines-version": ["@prisma/engines-version@6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", "", {}, "sha512-7tw1qs/9GWSX6qbZs4He09TOTg1ff3gYsB3ubaVNN0Pp1zLm9NC5C5MZShtkz7TyQjx7blhpknB7HwEhlG+PrQ=="],
|
||||
"@prisma/engines-version": ["@prisma/engines-version@6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", "", {}, "sha512-R/ZcMuaWZT2UBmgX3Ko6PAV3f8//ZzsjRIG1eKqp3f2rqEqVtCv+mtzuH2rBPUC9ujJ5kCb9wwpxeyCkLcHVyA=="],
|
||||
|
||||
"@prisma/fetch-engine": ["@prisma/fetch-engine@6.2.1", "", { "dependencies": { "@prisma/debug": "6.2.1", "@prisma/engines-version": "6.2.0-14.4123509d24aa4dede1e864b46351bf2790323b69", "@prisma/get-platform": "6.2.1" } }, "sha512-OO7O9d6Mrx2F9i+Gu1LW+DGXXyUFkP7OE5aj9iBfA/2jjDXEJjqa9X0ZmM9NZNo8Uo7ql6zKm6yjDcbAcRrw1A=="],
|
||||
"@prisma/fetch-engine": ["@prisma/fetch-engine@6.3.1", "", { "dependencies": { "@prisma/debug": "6.3.1", "@prisma/engines-version": "6.3.0-17.acc0b9dd43eb689cbd20c9470515d719db10d0b0", "@prisma/get-platform": "6.3.1" } }, "sha512-HOf/0umOgt+/S2xtZze+FHKoxpVg4YpVxROr6g2YG09VsI3Ipyb+rGvD6QGbCqkq5NTWAAZoOGNL+oy7t+IhaQ=="],
|
||||
|
||||
"@prisma/generator-helper": ["@prisma/generator-helper@6.2.1", "", { "dependencies": { "@prisma/debug": "6.2.1" } }, "sha512-7Ws8DCXGan7hhaFMERXYdmhsudvSzEsrTttJEC7ubZJidvyimS12m3xpM+dLTt+NAShJ7Op7PgF+Mal2jf6xfg=="],
|
||||
|
||||
"@prisma/get-platform": ["@prisma/get-platform@6.2.1", "", { "dependencies": { "@prisma/debug": "6.2.1" } }, "sha512-zp53yvroPl5m5/gXYLz7tGCNG33bhG+JYCm74ohxOq1pPnrL47VQYFfF3RbTZ7TzGWCrR3EtoiYMywUBw7UK6Q=="],
|
||||
"@prisma/get-platform": ["@prisma/get-platform@6.3.1", "", { "dependencies": { "@prisma/debug": "6.3.1" } }, "sha512-AYLq6Hk9xG73JdLWJ3Ip9Wg/vlP7xPvftGBalsPzKDOHr/ImhwJ09eS8xC2vNT12DlzGxhfk8BkL0ve2OriNhQ=="],
|
||||
|
||||
"@repeaterjs/repeater": ["@repeaterjs/repeater@3.0.6", "", {}, "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.30.1", "", { "os": "android", "cpu": "arm" }, "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q=="],
|
||||
"@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@28.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.30.1", "", { "os": "android", "cpu": "arm64" }, "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w=="],
|
||||
"@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q=="],
|
||||
"@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.1", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA=="],
|
||||
"@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="],
|
||||
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.30.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ=="],
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.32.0", "", { "os": "android", "cpu": "arm" }, "sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg=="],
|
||||
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw=="],
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg=="],
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug=="],
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw=="],
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.32.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA=="],
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ=="],
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.30.1", "", { "os": "linux", "cpu": "none" }, "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ=="],
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A=="],
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.30.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw=="],
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.30.1", "", { "os": "linux", "cpu": "none" }, "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw=="],
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.30.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA=="],
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg=="],
|
||||
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.32.0", "", { "os": "linux", "cpu": "none" }, "sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow=="],
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.32.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw=="],
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.32.0", "", { "os": "linux", "cpu": "none" }, "sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.30.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw=="],
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.32.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og=="],
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.32.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA=="],
|
||||
|
||||
"@sinclair/typebox": ["@sinclair/typebox@0.31.28", "", {}, "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ=="],
|
||||
|
||||
"@storybook/addon-actions": ["@storybook/addon-actions@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "@types/uuid": "^9.0.1", "dequal": "^2.0.2", "polished": "^4.2.2", "uuid": "^9.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-6CW9+17rk5eNx6I8EKqCxRKtsJFTR/lHL+xiJ6/iBWApIm8sg63vhXvUTJ58UixmIkT5oLh0+ESNPh+x10D8fw=="],
|
||||
"@storybook/addon-actions": ["@storybook/addon-actions@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "@types/uuid": "^9.0.1", "dequal": "^2.0.2", "polished": "^4.2.2", "uuid": "^9.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-oBBSpOJ6/rCdbdU1JxGCLernaCxALLWDIeZk6tLoQbtbsx/czD1sodqjcujjKwbQwNyZTf8xR8zsCSzG06dWDw=="],
|
||||
|
||||
"@storybook/addon-backgrounds": ["@storybook/addon-backgrounds@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-lzyFLs7niNsqlhH5kdUrp7htLiMIcjY50VLWe0PaeJ6T6GZ7X9qhQzROAUV6cGqzyd8A6y/LzIUntDPMVEm/6g=="],
|
||||
"@storybook/addon-backgrounds": ["@storybook/addon-backgrounds@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-4NFRFblPbRP3D4o4sSbJ1x9SMncP4+SHdSqKIovTjb+zOhqYPFYWMTinzEndUnBSDGREldHUvHjROuxrD/0qzA=="],
|
||||
|
||||
"@storybook/addon-controls": ["@storybook/addon-controls@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "dequal": "^2.0.2", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-1fivx77A/ahObrPl0L66o9i9MUNfqXxsrpekne5gjMNXw9XJFIRNUe/ddL4CMmwu7SgVbj2QV+q5E5mlnZNTJw=="],
|
||||
"@storybook/addon-controls": ["@storybook/addon-controls@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "dequal": "^2.0.2", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-RA/SPXW1chfsWaV8Lv/aXJNZJ8hasDEXQ1C5xRCt+T8DFvPqRZGgUfIpsiZ80AKp5RzufT9KL+39piPMljhKXA=="],
|
||||
|
||||
"@storybook/addon-docs": ["@storybook/addon-docs@8.5.0", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/blocks": "8.5.0", "@storybook/csf-plugin": "8.5.0", "@storybook/react-dom-shim": "8.5.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-REwLSr1VgOVNJZwP3y3mldhOjBHlM5fqTvq/tC8NaYpAzx9O4rZdoUSZxW3tYtoNoYrHpB8kzRTeZl8WSdKllw=="],
|
||||
"@storybook/addon-docs": ["@storybook/addon-docs@8.5.1", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/blocks": "8.5.1", "@storybook/csf-plugin": "8.5.1", "@storybook/react-dom-shim": "8.5.1", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-XhELkuNFOa8q2rF/AXTwnKZth7lCFqkfR5VuEAQ+g9hv2p6I/VGlTddylzjdaZKhiy4p8O9DrzGdLFj+oxOpMw=="],
|
||||
|
||||
"@storybook/addon-essentials": ["@storybook/addon-essentials@8.5.0", "", { "dependencies": { "@storybook/addon-actions": "8.5.0", "@storybook/addon-backgrounds": "8.5.0", "@storybook/addon-controls": "8.5.0", "@storybook/addon-docs": "8.5.0", "@storybook/addon-highlight": "8.5.0", "@storybook/addon-measure": "8.5.0", "@storybook/addon-outline": "8.5.0", "@storybook/addon-toolbars": "8.5.0", "@storybook/addon-viewport": "8.5.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-RrHRdaw2j3ugZiYQ6OHt3Ff08ID4hwAvipqULEsbEnEw3VlXOaW/MT5e2M7kW3MHskQ3iJ6XAD1Y1rNm432Pzw=="],
|
||||
"@storybook/addon-essentials": ["@storybook/addon-essentials@8.5.1", "", { "dependencies": { "@storybook/addon-actions": "8.5.1", "@storybook/addon-backgrounds": "8.5.1", "@storybook/addon-controls": "8.5.1", "@storybook/addon-docs": "8.5.1", "@storybook/addon-highlight": "8.5.1", "@storybook/addon-measure": "8.5.1", "@storybook/addon-outline": "8.5.1", "@storybook/addon-toolbars": "8.5.1", "@storybook/addon-viewport": "8.5.1", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-jPGrZ7j+RWistrsgpvjUBvLpWRuOeDNdV014ggHBxDMNX9GWb1GSubWW2Tlo7BfOuUvjICVAjI4KMp/IC/jwZg=="],
|
||||
|
||||
"@storybook/addon-highlight": ["@storybook/addon-highlight@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-/JxYzMK5aJSYs0K/0eAEFyER2dMoxqwM891MdnkNwLFdyrM58lzHee00F9oEX6zeQoRUNQPRepq0ui2PvbTMGw=="],
|
||||
"@storybook/addon-highlight": ["@storybook/addon-highlight@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-nhwx39DuWy2OFP+AQg8EzYP3giM+rQ0OIdAXgAjDVdKk2sGj43gwNYS9wQzXeczEUiSEjQk0JJwBqjF+GtSrag=="],
|
||||
|
||||
"@storybook/addon-interactions": ["@storybook/addon-interactions@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/instrumenter": "8.5.0", "@storybook/test": "8.5.0", "polished": "^4.2.2", "ts-dedent": "^2.2.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-vX1a8qS7o/W3kEzfL/CqOj/Rr6UlGLT/n0KXMpfIhx63tzxe1a1qGpFLL0h0zqAVPHZIOu9humWMKri5Iny6oA=="],
|
||||
"@storybook/addon-interactions": ["@storybook/addon-interactions@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/instrumenter": "8.5.1", "@storybook/test": "8.5.1", "polished": "^4.2.2", "ts-dedent": "^2.2.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-tXCKBIWjwhVuSRRoEiPx+u0D4oqMkctTzysfoCw2sqftIT8t2yHyviX29s87z2NH+DNqzBGGDG1UUaLe5qq3Fw=="],
|
||||
|
||||
"@storybook/addon-measure": ["@storybook/addon-measure@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "tiny-invariant": "^1.3.1" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-e8pJy2sICyj0Ff0W1PFc6HPE6PqcjnnHtfuDaO3M9uSKJLYkpTWJ8i1VSP178f8seq44r5/PdQCHqs5q5l3zgw=="],
|
||||
"@storybook/addon-measure": ["@storybook/addon-measure@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "tiny-invariant": "^1.3.1" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-Goc/IRh0aYT7zfDP9fgwL+DFX52DylanoBf0uGf59IQ7sEJHbwWm0OpiSEDo+NbtytbG83UOQamT7aQxhQo7Zw=="],
|
||||
|
||||
"@storybook/addon-outline": ["@storybook/addon-outline@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-r12sk1b38Ph6NroWAOTfjbJ/V+gDobm7tKQQlbSDf6fgX7cqyPHmKjfNDCOCQpXouZm/Jm+41zd758PW+Yt4ng=="],
|
||||
"@storybook/addon-outline": ["@storybook/addon-outline@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-LM3wG5bUgAAEgDS4MD1dw2VStduSYTMc/rNgaTExVVr7pPeuAgkfyIUriP3P0i7x5jweSb2aGzaTuy3PUHAWfg=="],
|
||||
|
||||
"@storybook/addon-styling-webpack": ["@storybook/addon-styling-webpack@1.0.1", "", { "dependencies": { "@storybook/node-logger": "^8.0.0-alpha.10" }, "peerDependencies": { "webpack": "^5.0.0" } }, "sha512-5n+SXPfMTc4m7sWaJWPWjoHYWc6/B111M2Ia55toQ3GV4ON4vVlTgH9FX+EgCkDticElj99HLTMDJkHRj2yvkg=="],
|
||||
|
||||
"@storybook/addon-svelte-csf": ["@storybook/addon-svelte-csf@5.0.0-next.23", "", { "dependencies": { "@storybook/csf": "^0.1.11", "@storybook/docs-tools": "^8.0.0", "@storybook/types": "^8.0.0", "dedent": "^1.5.3", "es-toolkit": "^1.26.1", "esrap": "^1.2.2", "magic-string": "^0.30.12", "svelte-ast-print": "^0.4.0", "zimmerframe": "^1.1.2" }, "peerDependencies": { "@storybook/svelte": "^8.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0 || ^5.0.0", "svelte": "^5.0.0", "vite": "^5.0.0 || ^6.0.0" } }, "sha512-GAdvA1f5wMhfrkP9znwDZzBFEopkELTRz8US+5XqucYHFfATiJIOALB+dW+CsUuknsfPxaA/Yqz9314ZYrT4iQ=="],
|
||||
|
||||
"@storybook/addon-themes": ["@storybook/addon-themes@8.5.0", "", { "dependencies": { "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-pBNut4sLfcOeLBvWdNAJ3cxv/BfMSTmJcUtSzE4G+1pVNsBbGF+T2f/GM0IjaM0K8Ft03VDzeEAB64nluDS4RA=="],
|
||||
"@storybook/addon-themes": ["@storybook/addon-themes@8.5.1", "", { "dependencies": { "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-xgPRznXvD95iir+mK/WMJ5QmPeiWfNcCttCNeSVsqHmSlN+5OW28N91V0tZmqDstBW5/qTd1itar23Xrpf8qKA=="],
|
||||
|
||||
"@storybook/addon-toolbars": ["@storybook/addon-toolbars@8.5.0", "", { "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-q3yYYO2WX8K2DYNM++FzixGDjzYaeREincgsl2WXYXrcuGb5hkOoOgRiAQL8Nz9NQ1Eo+B/yZxrhG/5VoVhUUQ=="],
|
||||
"@storybook/addon-toolbars": ["@storybook/addon-toolbars@8.5.1", "", { "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-01Odzujfq/g9u1ZTmH/X3I9cCnsNzG/wuyhzFr/T99jerx8QG/U45iYYph2Ytw6A5AtYyCnPYmsTsI+phjUvuA=="],
|
||||
|
||||
"@storybook/addon-viewport": ["@storybook/addon-viewport@8.5.0", "", { "dependencies": { "memoizerific": "^1.11.3" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-MlhVELImk9YzjEgGR2ciLC8d5tUSGcO7my4kWIClN0VyTRcvG4ZfwrsEC+jN3/l52nrgjLmKrDX5UAGZm6w5mQ=="],
|
||||
"@storybook/addon-viewport": ["@storybook/addon-viewport@8.5.1", "", { "dependencies": { "memoizerific": "^1.11.3" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-kKCXZT3keUEQulv2tOzRSl/GdFA2JeFjHmks/n7qQLY0zDqdx/C7K9jUECcrOJiLclZwTJvHA3YXrglVJoa6Hw=="],
|
||||
|
||||
"@storybook/blocks": ["@storybook/blocks@8.5.0", "", { "dependencies": { "@storybook/csf": "0.1.12", "@storybook/icons": "^1.2.12", "ts-dedent": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "^8.5.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-2sTOgjH/JFOgWnpqkKjpKVvKAgUaC9ZBjH1gnCoA5dne/SDafYaCAYfv6yZn7g2Xm1sTxWCAmMIUkYSALeWr+w=="],
|
||||
"@storybook/blocks": ["@storybook/blocks@8.5.1", "", { "dependencies": { "@storybook/csf": "0.1.12", "@storybook/icons": "^1.2.12", "ts-dedent": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "^8.5.1" }, "optionalPeers": ["react", "react-dom"] }, "sha512-xUjnOa9udmHhlBTZ+bmMHeU1M9a5OnvnX8urQ0TrNpSyHH7HoPd3xZC4fzz73nSJNMVHIYMZYsz2pj/WfeA/hg=="],
|
||||
|
||||
"@storybook/builder-vite": ["@storybook/builder-vite@8.5.0", "", { "dependencies": { "@storybook/csf-plugin": "8.5.0", "browser-assert": "^1.2.1", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.0", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-GVJFjAxX/mL3bmXX6N619ShuYprkh6Ix08JU6QGNf/tTkG92BxjgCqQdfovBrviDhFyO2bhkdlEp6ujMo5CbZA=="],
|
||||
"@storybook/builder-vite": ["@storybook/builder-vite@8.5.1", "", { "dependencies": { "@storybook/csf-plugin": "8.5.1", "browser-assert": "^1.2.1", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^8.5.1", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-m7nzMmXL8ySRDp3AWsd18xB/mRVFdGnCbXeC2HREQVsu1WFkvcHtksvF4x1BOeeL73eokD2/GzgpCjAS0xVvbw=="],
|
||||
|
||||
"@storybook/components": ["@storybook/components@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-DhaHtwfEcfWYj3ih/5RBSDHe3Idxyf+oHw2/DmaLKJX6MluhdK3ZqigjRcTmA9Gj/SbR4CkHEEtDzAvBlW0BYw=="],
|
||||
"@storybook/components": ["@storybook/components@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-dgZfIIRdI7yA9bYb1rhWzbvU4AnbndAeNhLouxHJkUR5r2Ycp9mJba5UNynN1slgDOxB+VMnq1fWKyfWQrBqnw=="],
|
||||
|
||||
"@storybook/core": ["@storybook/core@8.5.0", "", { "dependencies": { "@storybook/csf": "0.1.12", "better-opn": "^3.0.2", "browser-assert": "^1.2.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", "esbuild-register": "^3.5.0", "jsdoc-type-pratt-parser": "^4.0.0", "process": "^0.11.10", "recast": "^0.23.5", "semver": "^7.6.2", "util": "^0.12.5", "ws": "^8.2.3" }, "peerDependencies": { "prettier": "^2 || ^3" }, "optionalPeers": ["prettier"] }, "sha512-apborO6ynns7SeydBSqE9o0zT6JSU+VY4gLFPJROGcconvSW4bS5xtJCsgjlulceyWVxepFHGXl4jEZw+SktXA=="],
|
||||
"@storybook/core": ["@storybook/core@8.5.1", "", { "dependencies": { "@storybook/csf": "0.1.12", "better-opn": "^3.0.2", "browser-assert": "^1.2.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", "esbuild-register": "^3.5.0", "jsdoc-type-pratt-parser": "^4.0.0", "process": "^0.11.10", "recast": "^0.23.5", "semver": "^7.6.2", "util": "^0.12.5", "ws": "^8.2.3" }, "peerDependencies": { "prettier": "^2 || ^3" }, "optionalPeers": ["prettier"] }, "sha512-4zxjclENpZYuNY1fZJE4a7hd8Ho/SiOSN2B57fsIi1qCpKax3JU3J59ZcAWT0iidy5qgM2qMcWbrl0Bl/tWamA=="],
|
||||
|
||||
"@storybook/csf": ["@storybook/csf@0.1.13", "", { "dependencies": { "type-fest": "^2.19.0" } }, "sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q=="],
|
||||
"@storybook/csf": ["@storybook/csf@0.1.12", "", { "dependencies": { "type-fest": "^2.19.0" } }, "sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw=="],
|
||||
|
||||
"@storybook/csf-plugin": ["@storybook/csf-plugin@8.5.0", "", { "dependencies": { "unplugin": "^1.3.1" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-cs6ogviNyLG1h9J8Sb47U3DqIrQmn2EHm4ta3fpCeV3ABbrMgbzYyxtmybz4g/AwlDgjAZAt6PPcXkfCJ6p2CQ=="],
|
||||
"@storybook/csf-plugin": ["@storybook/csf-plugin@8.5.1", "", { "dependencies": { "unplugin": "^1.3.1" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-8GFrQgJ+/hzWAj9o4XK8m7UFPLxf0w3RwX0ZMPeb6zDhq/1BUE97AjKFb4Oexkh4I67Pycv4gRUOY9+tXF/1DA=="],
|
||||
|
||||
"@storybook/docs-tools": ["@storybook/docs-tools@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-W5C0Gu6FTqQaXGMYtlPNSPgRHbGS9bcvGRWxBA3+V6LSxL4he/yegwz/AH5dfLVI2PCHVedNtIv+yHKM+a2E3w=="],
|
||||
"@storybook/docs-tools": ["@storybook/docs-tools@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-0mPWEnYhAMYeSGWKK9NNbdWyDMIy9HB3cPdY6NKkvHcw7Sy9cmQtvuvwVPptjdcf0BShJkMTJjmf5h9YNhJPmQ=="],
|
||||
|
||||
"@storybook/global": ["@storybook/global@5.0.0", "", {}, "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ=="],
|
||||
|
||||
"@storybook/icons": ["@storybook/icons@1.3.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" } }, "sha512-Nz/UzeYQdUZUhacrPyfkiiysSjydyjgg/p0P9HxB4p/WaJUUjMAcaoaLgy3EXx61zZJ3iD36WPuDkZs5QYrA0A=="],
|
||||
"@storybook/icons": ["@storybook/icons@1.3.2", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" } }, "sha512-t3xcbCKkPvqyef8urBM0j/nP6sKtnlRkVgC+8JTbTAZQjaTmOjes3byEgzs89p4B/K6cJsg9wLW2k3SknLtYJw=="],
|
||||
|
||||
"@storybook/instrumenter": ["@storybook/instrumenter@8.5.0", "", { "dependencies": { "@storybook/global": "^5.0.0", "@vitest/utils": "^2.1.1" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-eZ/UY6w4U2vay+wX7QVwKiRoyMzZscuv6v4k4r8BlmHPFWbhiZDO9S2GsG16UkyKnrQrYk432he70n7hn1Xvmg=="],
|
||||
"@storybook/instrumenter": ["@storybook/instrumenter@8.5.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "@vitest/utils": "^2.1.1" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-wMAhsIzwOh/xXKANAP3IbtXxRWFAZtpRisB0sy8WVTPS3a1L1cA6X+U80Ex/omek6L0FZwKZSKmmfkDeZkYnCQ=="],
|
||||
|
||||
"@storybook/manager-api": ["@storybook/manager-api@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-Ildriueo3eif4M+gMlMxu/mrBIbAnz8+oesmQJKdzZfe/U9eQTI9OUqJsxx/IVBmdzQ3ySsgNmzj5VweRkse4A=="],
|
||||
"@storybook/manager-api": ["@storybook/manager-api@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-Oj9kPYbp/82LRQ+rsc0ZH0fkzeiT2U1kvubmNiRjtopQHCP3UTVnvWIXC9zSRFKmS+NaAdd0JYsIBvE8fjnoqQ=="],
|
||||
|
||||
"@storybook/node-logger": ["@storybook/node-logger@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-dQqFZeT7AnRRaHNNicQWnuG+dNJnEFLxiYpNg10veqjWaRBvLOInoawyVWHhhezaBbde7nXg10mWZ8CMlPfevQ=="],
|
||||
"@storybook/node-logger": ["@storybook/node-logger@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-O12j4IdpaM5Z/CCWU5NyS/6vALFc5vChwfsWEWFfE3lOUMfLHYuQgH+x5XE6Ctq53ua2IHGOZAmwLrrpxVx4dg=="],
|
||||
|
||||
"@storybook/preview-api": ["@storybook/preview-api@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-g0XbD54zMUkl6bpuA7qEBCE9rW1QV6KKmwkO4bkxMOJcMke3x9l00JTaYn7Un8wItjXiS3BIG15B6mnfBG7fng=="],
|
||||
"@storybook/preview-api": ["@storybook/preview-api@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-fLR7nvAbjHVLazDA6CLy9O/bpBzKDKqxyBp6SybTBPYa76IzsX8ITSMMt1YcP6rOGhVgcKNA9iBNxRddjLIV0Q=="],
|
||||
|
||||
"@storybook/react-dom-shim": ["@storybook/react-dom-shim@8.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "^8.5.0" } }, "sha512-7P8xg4FiuFpM6kQOzZynno+0zyLVs8NgsmRK58t3JRZXbda1tzlxTXzvqx4hUevvbPJGjmrB0F3xTFH+8Otnvw=="],
|
||||
"@storybook/react-dom-shim": ["@storybook/react-dom-shim@8.5.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "^8.5.1" } }, "sha512-peDiT6A1zyODKd7tVQIiFNU42Iolca67h3kkOQPb7nm/Czf2yIa/BHw+yiNDZx82eCIEvBy1Xf7lnjH8PD61xA=="],
|
||||
|
||||
"@storybook/svelte": ["@storybook/svelte@8.5.0", "", { "dependencies": { "@storybook/components": "8.5.0", "@storybook/global": "^5.0.0", "@storybook/manager-api": "8.5.0", "@storybook/preview-api": "8.5.0", "@storybook/theming": "8.5.0", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.0.0", "type-fest": "~2.19" }, "peerDependencies": { "storybook": "^8.5.0", "svelte": "^4.0.0 || ^5.0.0" } }, "sha512-P3qG441QgSk6fOXcMT/PvkLcds6fX36PcxY5CpV+xDwaxtx6ghV+2FZL85scdgX+EeihJ9xnNiUGLapK9Pltuw=="],
|
||||
"@storybook/svelte": ["@storybook/svelte@8.5.1", "", { "dependencies": { "@storybook/components": "8.5.1", "@storybook/global": "^5.0.0", "@storybook/manager-api": "8.5.1", "@storybook/preview-api": "8.5.1", "@storybook/theming": "8.5.1", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.0.0", "type-fest": "~2.19" }, "peerDependencies": { "storybook": "^8.5.1", "svelte": "^4.0.0 || ^5.0.0" } }, "sha512-DtApr2+wCKVp5kx/K9a55bzVVfypTa26xU4SC7UvjhKmvein/BNNilhgUh9th4wZApipNYKsfdXYDQBwzSYAOw=="],
|
||||
|
||||
"@storybook/svelte-vite": ["@storybook/svelte-vite@8.5.0", "", { "dependencies": { "@storybook/builder-vite": "8.5.0", "@storybook/svelte": "8.5.0", "magic-string": "^0.30.0", "svelte-preprocess": "^5.1.1", "svelte2tsx": "^0.7.13", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.2.0", "typescript": "^4.9.4 || ^5.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "storybook": "^8.5.0", "svelte": "^4.0.0 || ^5.0.0", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-lHo7txeqXZh93oXBXZi5ZIQ3m5CyWNEPatnbyBq06oLlCwNSdhUC4+ex3lTiqTY/aitQXf/BkRiKJfVNneB2jw=="],
|
||||
"@storybook/svelte-vite": ["@storybook/svelte-vite@8.5.1", "", { "dependencies": { "@storybook/builder-vite": "8.5.1", "@storybook/svelte": "8.5.1", "magic-string": "^0.30.0", "svelte-preprocess": "^5.1.1", "svelte2tsx": "^0.7.13", "sveltedoc-parser": "^4.2.1", "ts-dedent": "^2.2.0", "typescript": "^4.9.4 || ^5.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", "storybook": "^8.5.1", "svelte": "^4.0.0 || ^5.0.0", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-hPDbkZvvvgxIqua48zep5JZFMo/cOl/vJ9n2A5iI5FMloxxkQ/aJFmJu80VvChaGC3D+lwZdz+vhiK+ZoPqaSQ=="],
|
||||
|
||||
"@storybook/sveltekit": ["@storybook/sveltekit@8.5.0", "", { "dependencies": { "@storybook/addon-actions": "8.5.0", "@storybook/builder-vite": "8.5.0", "@storybook/svelte": "8.5.0", "@storybook/svelte-vite": "8.5.0" }, "peerDependencies": { "storybook": "^8.5.0", "svelte": "^4.0.0 || ^5.0.0", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-Gm9elJTiFDrECkkJzKPygyHwKzjtkaBDeilHfH7UNsrgjP8JlNnQeRybVKWGy2lrVUB8yGJfEKys+qELYSIo3A=="],
|
||||
"@storybook/sveltekit": ["@storybook/sveltekit@8.5.1", "", { "dependencies": { "@storybook/addon-actions": "8.5.1", "@storybook/builder-vite": "8.5.1", "@storybook/svelte": "8.5.1", "@storybook/svelte-vite": "8.5.1" }, "peerDependencies": { "storybook": "^8.5.1", "svelte": "^4.0.0 || ^5.0.0", "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" } }, "sha512-XI0Nq9SjMErCaEPx30S8MrUK0N50k58iaig6Gg/cLkBE1VmBjdZqMynpjkm7/dU4/iUis9vNg0st8nOXOIsjUg=="],
|
||||
|
||||
"@storybook/test": ["@storybook/test@8.5.0", "", { "dependencies": { "@storybook/csf": "0.1.12", "@storybook/global": "^5.0.0", "@storybook/instrumenter": "8.5.0", "@testing-library/dom": "10.4.0", "@testing-library/jest-dom": "6.5.0", "@testing-library/user-event": "14.5.2", "@vitest/expect": "2.0.5", "@vitest/spy": "2.0.5" }, "peerDependencies": { "storybook": "^8.5.0" } }, "sha512-M/DdPlI6gwL7NGkK5o7GYjdEBp95AsFEUtW29zQfnVIAngYugzi3nIuM/XkQHunidVdAZCYjw2s2Yhhsx/m9sw=="],
|
||||
"@storybook/test": ["@storybook/test@8.5.1", "", { "dependencies": { "@storybook/csf": "0.1.12", "@storybook/global": "^5.0.0", "@storybook/instrumenter": "8.5.1", "@testing-library/dom": "10.4.0", "@testing-library/jest-dom": "6.5.0", "@testing-library/user-event": "14.5.2", "@vitest/expect": "2.0.5", "@vitest/spy": "2.0.5" }, "peerDependencies": { "storybook": "^8.5.1" } }, "sha512-V0sEXqL5kS0YKugCqWgmCpNODdlCCiVlPqm3i+E2+G97DR980BwXf8J6VPscQDRS9ZG39BrM83Aau6Anxrt1Tg=="],
|
||||
|
||||
"@storybook/theming": ["@storybook/theming@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-591LbOj/HMmHYUfLgrMerxhF1A9mY61HWKxcRpB6xxalc1Xw1kRtQ49DcwuTXnUu9ktBB3nuOzPNPQPFSh/7PQ=="],
|
||||
"@storybook/theming": ["@storybook/theming@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-sg61vY1gM8w42CIi28vo//6E1gHgHLNBNaRhkfvLFpu9PuhAcVWLwBDZq0BoKmDMxRxbSPV2gvIKeXdOtbSCJw=="],
|
||||
|
||||
"@storybook/types": ["@storybook/types@8.5.0", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-5orPpfLvSksGH341ibmpFnV86yqlZMbvNax+a+z1h56UKRA+4c/hgdRQl1brs7YaQzrgJ2wUX7PAlJjBJ1erUQ=="],
|
||||
"@storybook/types": ["@storybook/types@8.5.1", "", { "peerDependencies": { "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "sha512-bD5KZ9628licnzMX4pFwWv6opxh3UTZr4zBO796Mm1lMEcGIqs9qFHDbbxly5tuV6IvI6nOSnm7djAFlba7YgQ=="],
|
||||
|
||||
"@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@3.3.1", "", { "dependencies": { "import-meta-resolve": "^4.1.0" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-5Sc7WAxYdL6q9j/+D0jJKjGREGlfIevDyHSQ2eNETHcB1TKlQWHcAo8AS8H1QdjNvSXpvOwNjykDUHPEAyGgdQ=="],
|
||||
"@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.2.12", "", { "dependencies": { "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ=="],
|
||||
|
||||
"@sveltejs/kit": ["@sveltejs/kit@2.15.3", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0", "tiny-glob": "^0.2.9" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-yI1iF1ldC+nyMFuA1cV+IMOROaGu6ogW0WNlTuPU5/3tGk8pQlwOtlbguGY4Fsp8Qf6pQWmG/ZUXRDrhAt62dg=="],
|
||||
"@sveltejs/kit": ["@sveltejs/kit@2.16.1", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-2pF5sgGJx9brYZ/9nNDYnh5KX0JguPF14dnvvtf/MqrvlWrDj/e7Rk3LBJPecFLLK1GRs6ZniD24gFPqZm/NFw=="],
|
||||
|
||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@5.0.3", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", "debug": "^4.4.0", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.15", "vitefu": "^1.0.4" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.0.0" } }, "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw=="],
|
||||
|
||||
|
|
@ -455,7 +463,7 @@
|
|||
|
||||
"@types/btoa-lite": ["@types/btoa-lite@1.0.2", "", {}, "sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.1.16", "", { "dependencies": { "bun-types": "1.1.43" } }, "sha512-E+ue6NMcn4FXC5bDRE1W/BXUVs01h5Mt02qH8/8HGCox9akuh8KNOFdwvaQS9TDgT2RmUyJYFRRqA60WtTnm2g=="],
|
||||
"@types/bun": ["@types/bun@1.2.0", "", { "dependencies": { "bun-types": "1.2.0" } }, "sha512-5N1JqdahfpBlAv4wy6svEYcd/YfO2GNrbL95JOmFx8nkE6dbK4R0oSE5SpBA4vBRqgrOUAXF8Dpiz+gi7r80SA=="],
|
||||
|
||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
||||
|
||||
|
|
@ -467,35 +475,39 @@
|
|||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/jsonwebtoken": ["@types/jsonwebtoken@9.0.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg=="],
|
||||
"@types/jsonwebtoken": ["@types/jsonwebtoken@9.0.8", "", { "dependencies": { "@types/ms": "*", "@types/node": "*" } }, "sha512-7fx54m60nLFUVYlxAB1xpe9CBWX2vSrk50Y6ogRJ1v5xxtba7qXTg5BgYDN5dq+yuQQ9HaVlHJyAAt1/mxryFg=="],
|
||||
|
||||
"@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="],
|
||||
|
||||
"@types/node": ["@types/node@20.12.14", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg=="],
|
||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||
|
||||
"@types/node": ["@types/node@22.10.10", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww=="],
|
||||
|
||||
"@types/pug": ["@types/pug@2.0.10", "", {}, "sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA=="],
|
||||
|
||||
"@types/react": ["@types/react@19.0.7", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-MoFsEJKkAtZCrC1r6CM8U22GzhG7u2Wir8ons/aCKH6MBdD1ibV24zOSSkdZVUKqN5i396zG5VKLYZ3yaUZdLA=="],
|
||||
"@types/react": ["@types/react@19.0.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw=="],
|
||||
|
||||
"@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="],
|
||||
|
||||
"@types/uuid": ["@types/uuid@9.0.8", "", {}, "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.5.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA=="],
|
||||
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.20.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.20.0", "@typescript-eslint/type-utils": "8.20.0", "@typescript-eslint/utils": "8.20.0", "@typescript-eslint/visitor-keys": "8.20.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-naduuphVw5StFfqp4Gq4WhIBE2gN1GEmMUExpJYknZJdRnc+2gDzB8Z3+5+/Kv33hPQRDGzQO/0opHE72lZZ6A=="],
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.21.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.21.0", "@typescript-eslint/type-utils": "8.21.0", "@typescript-eslint/utils": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.20.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.20.0", "@typescript-eslint/types": "8.20.0", "@typescript-eslint/typescript-estree": "8.20.0", "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-gKXG7A5HMyjDIedBi6bUrDcun8GIjnI8qOwVLiY3rx6T/sHP/19XLJOnIq/FgQvWLHja5JN/LSE7eklNBr612g=="],
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.21.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.21.0", "@typescript-eslint/types": "8.21.0", "@typescript-eslint/typescript-estree": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA=="],
|
||||
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.20.0", "", { "dependencies": { "@typescript-eslint/types": "8.20.0", "@typescript-eslint/visitor-keys": "8.20.0" } }, "sha512-J7+VkpeGzhOt3FeG1+SzhiMj9NzGD/M6KoGn9f4dbz3YzK9hvbhVTmLj/HiTp9DazIzJ8B4XcM80LrR9Dm1rJw=="],
|
||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.21.0", "", { "dependencies": { "@typescript-eslint/types": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0" } }, "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA=="],
|
||||
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.20.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.20.0", "@typescript-eslint/utils": "8.20.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-bPC+j71GGvA7rVNAHAtOjbVXbLN5PkwqMvy1cwGeaxUoRQXVuKCebRoLzm+IPW/NtFFpstn1ummSIasD5t60GA=="],
|
||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.21.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.21.0", "@typescript-eslint/utils": "8.21.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ=="],
|
||||
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.20.0", "", {}, "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA=="],
|
||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.21.0", "", {}, "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.20.0", "", { "dependencies": { "@typescript-eslint/types": "8.20.0", "@typescript-eslint/visitor-keys": "8.20.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.8.0" } }, "sha512-Y7ncuy78bJqHI35NwzWol8E0X7XkRVS4K4P4TCyzWkOJih5NDvtoRDW4Ba9YJJoB2igm9yXDdYI/+fkiiAxPzA=="],
|
||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.21.0", "", { "dependencies": { "@typescript-eslint/types": "8.21.0", "@typescript-eslint/visitor-keys": "8.21.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.0.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.8.0" } }, "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg=="],
|
||||
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.20.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.20.0", "@typescript-eslint/types": "8.20.0", "@typescript-eslint/typescript-estree": "8.20.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-dq70RUw6UK9ei7vxc4KQtBRk7qkHZv447OUZ6RPQMQl71I3NZxQJX/f32Smr+iqWrB02pHKn2yAdHBb0KNrRMA=="],
|
||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.21.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.21.0", "@typescript-eslint/types": "8.21.0", "@typescript-eslint/typescript-estree": "8.21.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.20.0", "", { "dependencies": { "@typescript-eslint/types": "8.20.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-v/BpkeeYAsPkKCkR8BDwcno0llhzWVqPOamQrAEMdpZav2Y9OVjd9dwJyBLJWwf335B5DmlifECIkZRJCaGaHA=="],
|
||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.21.0", "", { "dependencies": { "@typescript-eslint/types": "8.21.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w=="],
|
||||
|
||||
"@vitest/expect": ["@vitest/expect@2.0.5", "", { "dependencies": { "@vitest/spy": "2.0.5", "@vitest/utils": "2.0.5", "chai": "^5.1.1", "tinyrainbow": "^1.2.0" } }, "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA=="],
|
||||
|
||||
|
|
@ -635,7 +647,7 @@
|
|||
|
||||
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
|
||||
|
||||
"bun-types": ["bun-types@1.1.43", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-W0wCtVH+bwFp7p3Zgs03CqxEDmXxEvmmUM/FBKgWIv9T8gyeotvIjIbHzuDScc2DphhRNtr7hJLCR5PspYL5qw=="],
|
||||
"bun-types": ["bun-types@1.2.0", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-KEaJxyZfbV/c4eyG0vyehDpYmBGreNiQbZIqvVHJwZ4BmeuWlNZ7EAzMN2Zcd7ailmS/tGVW0BgYbGf+lGEpWw=="],
|
||||
|
||||
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
|
||||
|
||||
|
|
@ -651,7 +663,7 @@
|
|||
|
||||
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
|
||||
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001692", "", {}, "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A=="],
|
||||
"caniuse-lite": ["caniuse-lite@1.0.30001695", "", {}, "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw=="],
|
||||
|
||||
"chai": ["chai@5.1.2", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw=="],
|
||||
|
||||
|
|
@ -661,7 +673,7 @@
|
|||
|
||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
||||
|
||||
"chromatic": ["chromatic@11.25.0", "", { "peerDependencies": { "@chromatic-com/cypress": "^0.*.* || ^1.0.0", "@chromatic-com/playwright": "^0.*.* || ^1.0.0" }, "optionalPeers": ["@chromatic-com/cypress", "@chromatic-com/playwright"], "bin": { "chroma": "dist/bin.js", "chromatic": "dist/bin.js", "chromatic-cli": "dist/bin.js" } }, "sha512-P2BVe0rRLS9WM+eSG3u1SRg0Mi2vopsdPs2FiXwUiPqZ6hs9fe66d3Pnt7CfQ22v2jThuPEXYjYEeuL75a16Bw=="],
|
||||
"chromatic": ["chromatic@11.25.1", "", { "peerDependencies": { "@chromatic-com/cypress": "^0.*.* || ^1.0.0", "@chromatic-com/playwright": "^0.*.* || ^1.0.0" }, "optionalPeers": ["@chromatic-com/cypress", "@chromatic-com/playwright"], "bin": { "chroma": "dist/bin.js", "chromatic": "dist/bin.js", "chromatic-cli": "dist/bin.js" } }, "sha512-D0NdcGOSy84hqgNnSY7FM4TzB77RymRTowjm4hb1CV4wbk1djKTV4SJbbYVCzHFD+n/NOg/wtZ9Y7sjiRdy8dA=="],
|
||||
|
||||
"chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="],
|
||||
|
||||
|
|
@ -685,10 +697,12 @@
|
|||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
"commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
||||
"commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="],
|
||||
|
||||
"comment-json": ["comment-json@4.2.5", "", { "dependencies": { "array-timsort": "^1.0.3", "core-util-is": "^1.0.3", "esprima": "^4.0.1", "has-own-prop": "^2.0.0", "repeat-string": "^1.6.1" } }, "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw=="],
|
||||
|
||||
"commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="],
|
||||
|
||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||
|
||||
"consola": ["consola@3.2.3", "", {}, "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ=="],
|
||||
|
|
@ -773,7 +787,7 @@
|
|||
|
||||
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.83", "", {}, "sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ=="],
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.88", "", {}, "sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
|
||||
|
||||
|
|
@ -807,7 +821,7 @@
|
|||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"eslint": ["eslint@9.18.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "9.18.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.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", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA=="],
|
||||
"eslint": ["eslint@9.19.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", "@eslint/js": "9.19.0", "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.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", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA=="],
|
||||
|
||||
"eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="],
|
||||
|
||||
|
|
@ -837,7 +851,7 @@
|
|||
|
||||
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||
|
||||
|
|
@ -863,13 +877,13 @@
|
|||
|
||||
"fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="],
|
||||
|
||||
"fast-uri": ["fast-uri@3.0.5", "", {}, "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q=="],
|
||||
"fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="],
|
||||
|
||||
"fastparse": ["fastparse@1.1.2", "", {}, "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="],
|
||||
|
||||
"fastq": ["fastq@1.18.0", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw=="],
|
||||
|
||||
"fdir": ["fdir@6.4.2", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ=="],
|
||||
"fdir": ["fdir@6.4.3", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw=="],
|
||||
|
||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||
|
||||
|
|
@ -885,7 +899,7 @@
|
|||
|
||||
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
|
||||
|
||||
"for-each": ["for-each@0.3.3", "", { "dependencies": { "is-callable": "^1.1.3" } }, "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw=="],
|
||||
"for-each": ["for-each@0.3.4", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw=="],
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" } }, "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg=="],
|
||||
|
||||
|
|
@ -917,10 +931,6 @@
|
|||
|
||||
"globals": ["globals@15.14.0", "", {}, "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig=="],
|
||||
|
||||
"globalyzer": ["globalyzer@0.1.0", "", {}, "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q=="],
|
||||
|
||||
"globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="],
|
||||
|
||||
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
|
@ -987,6 +997,8 @@
|
|||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
|
||||
|
|
@ -1047,7 +1059,7 @@
|
|||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"lint-staged": ["lint-staged@15.4.1", "", { "dependencies": { "chalk": "~5.4.1", "commander": "~12.1.0", "debug": "~4.4.0", "execa": "~8.0.1", "lilconfig": "~3.1.3", "listr2": "~8.2.5", "micromatch": "~4.0.8", "pidtree": "~0.6.0", "string-argv": "~0.3.2", "yaml": "~2.6.1" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-P8yJuVRyLrm5KxCtFx+gjI5Bil+wO7wnTl7C3bXhvtTaAFGirzeB24++D0wGoUwxrUKecNiehemgCob9YL39NA=="],
|
||||
"lint-staged": ["lint-staged@15.4.3", "", { "dependencies": { "chalk": "^5.4.1", "commander": "^13.1.0", "debug": "^4.4.0", "execa": "^8.0.1", "lilconfig": "^3.1.3", "listr2": "^8.2.5", "micromatch": "^4.0.8", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g=="],
|
||||
|
||||
"listr2": ["listr2@8.2.5", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ=="],
|
||||
|
||||
|
|
@ -1197,7 +1209,7 @@
|
|||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
|
||||
|
||||
"pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="],
|
||||
|
||||
|
|
@ -1213,9 +1225,9 @@
|
|||
|
||||
"pirates": ["pirates@4.0.6", "", {}, "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg=="],
|
||||
|
||||
"playwright": ["playwright@1.49.1", "", { "dependencies": { "playwright-core": "1.49.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA=="],
|
||||
"playwright": ["playwright@1.50.0", "", { "dependencies": { "playwright-core": "1.50.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w=="],
|
||||
|
||||
"playwright-core": ["playwright-core@1.49.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg=="],
|
||||
"playwright-core": ["playwright-core@1.50.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ=="],
|
||||
|
||||
"polished": ["polished@4.3.1", "", { "dependencies": { "@babel/runtime": "^7.17.8" } }, "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA=="],
|
||||
|
||||
|
|
@ -1239,7 +1251,7 @@
|
|||
|
||||
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
|
||||
|
||||
"posthog-node": ["posthog-node@4.4.0", "", { "dependencies": { "axios": "^1.7.4" } }, "sha512-4FEFBuc4FDFkTEiCSIo7DFV0jpprlqfR/SzjVgg7E2rRvfxTW4J47IvCwSCo5C9lBeV0ujDubY/YArHG37aJIw=="],
|
||||
"posthog-node": ["posthog-node@4.4.1", "", { "dependencies": { "axios": "^1.7.4" } }, "sha512-o9G9sSvwWITrfSJgIUrPLJd//AYPGJNu5D+pSLxqiBvhUeicc/i639FvU0DPr1OsHiLDE2zHNMmLpa0mw4kBCg=="],
|
||||
|
||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||
|
||||
|
|
@ -1247,11 +1259,11 @@
|
|||
|
||||
"prettier-plugin-svelte": ["prettier-plugin-svelte@3.3.3", "", { "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw=="],
|
||||
|
||||
"prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.10", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-ndj2WLDaMzACnr1gAYZiZZLs5ZdOeBYgOsbBmHj3nvW/6q8h8PymsXiEnKvj/9qgCCAoHyvLOisoQdIcsDvIgw=="],
|
||||
"prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.11", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-YxaYSIvZPAqhrrEpRtonnrXdghZg1irNg4qrjboCXrpybLWVs55cW2N3juhspVJiO0JBvYJT8SYsJpc8OQSnsA=="],
|
||||
|
||||
"pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="],
|
||||
|
||||
"prisma": ["prisma@6.2.1", "", { "dependencies": { "@prisma/engines": "6.2.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "bin": { "prisma": "build/index.js" } }, "sha512-hhyM0H13pQleQ+br4CkzGizS5I0oInoeTw3JfLw1BRZduBSQxPILlJLwi+46wZzj9Je7ndyQEMGw/n5cN2fknA=="],
|
||||
"prisma": ["prisma@6.3.1", "", { "dependencies": { "@prisma/engines": "6.3.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "typescript": ">=5.1.0" }, "optionalPeers": ["typescript"], "bin": { "prisma": "build/index.js" } }, "sha512-JKCZWvBC3enxk51tY4TWzS4b5iRt4sSU1uHn2I183giZTvonXaQonzVtjLzpOHE7qu9MxY510kAtFGJwryKe3Q=="],
|
||||
|
||||
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
|
||||
|
||||
|
|
@ -1311,7 +1323,7 @@
|
|||
|
||||
"rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"rollup": ["rollup@4.30.1", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.30.1", "@rollup/rollup-android-arm64": "4.30.1", "@rollup/rollup-darwin-arm64": "4.30.1", "@rollup/rollup-darwin-x64": "4.30.1", "@rollup/rollup-freebsd-arm64": "4.30.1", "@rollup/rollup-freebsd-x64": "4.30.1", "@rollup/rollup-linux-arm-gnueabihf": "4.30.1", "@rollup/rollup-linux-arm-musleabihf": "4.30.1", "@rollup/rollup-linux-arm64-gnu": "4.30.1", "@rollup/rollup-linux-arm64-musl": "4.30.1", "@rollup/rollup-linux-loongarch64-gnu": "4.30.1", "@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", "@rollup/rollup-linux-riscv64-gnu": "4.30.1", "@rollup/rollup-linux-s390x-gnu": "4.30.1", "@rollup/rollup-linux-x64-gnu": "4.30.1", "@rollup/rollup-linux-x64-musl": "4.30.1", "@rollup/rollup-win32-arm64-msvc": "4.30.1", "@rollup/rollup-win32-ia32-msvc": "4.30.1", "@rollup/rollup-win32-x64-msvc": "4.30.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w=="],
|
||||
"rollup": ["rollup@4.32.0", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.32.0", "@rollup/rollup-android-arm64": "4.32.0", "@rollup/rollup-darwin-arm64": "4.32.0", "@rollup/rollup-darwin-x64": "4.32.0", "@rollup/rollup-freebsd-arm64": "4.32.0", "@rollup/rollup-freebsd-x64": "4.32.0", "@rollup/rollup-linux-arm-gnueabihf": "4.32.0", "@rollup/rollup-linux-arm-musleabihf": "4.32.0", "@rollup/rollup-linux-arm64-gnu": "4.32.0", "@rollup/rollup-linux-arm64-musl": "4.32.0", "@rollup/rollup-linux-loongarch64-gnu": "4.32.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.32.0", "@rollup/rollup-linux-riscv64-gnu": "4.32.0", "@rollup/rollup-linux-s390x-gnu": "4.32.0", "@rollup/rollup-linux-x64-gnu": "4.32.0", "@rollup/rollup-linux-x64-musl": "4.32.0", "@rollup/rollup-win32-arm64-msvc": "4.32.0", "@rollup/rollup-win32-ia32-msvc": "4.32.0", "@rollup/rollup-win32-x64-msvc": "4.32.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
|
|
@ -1385,7 +1397,7 @@
|
|||
|
||||
"std-env": ["std-env@3.8.0", "", {}, "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w=="],
|
||||
|
||||
"storybook": ["storybook@8.5.0", "", { "dependencies": { "@storybook/core": "8.5.0" }, "peerDependencies": { "prettier": "^2 || ^3" }, "optionalPeers": ["prettier"], "bin": { "sb": "./bin/index.cjs", "storybook": "./bin/index.cjs", "getstorybook": "./bin/index.cjs" } }, "sha512-cEx42OlCetManF+cONVJVYP7SYsnI2K922DfWKmZhebP0it0n6TUof4y5/XzJ8YUruwPgyclGLdX8TvdRuNSfw=="],
|
||||
"storybook": ["storybook@8.5.1", "", { "dependencies": { "@storybook/core": "8.5.1" }, "peerDependencies": { "prettier": "^2 || ^3" }, "optionalPeers": ["prettier"], "bin": { "sb": "./bin/index.cjs", "storybook": "./bin/index.cjs", "getstorybook": "./bin/index.cjs" } }, "sha512-HuaAFA97j2w4i/1EHKj6X4iDiVzPrXzQpmTEE1tLD1QXzqrQKKHse+Ggc8AGMuLTAzxA6xmrX9xibgMNWCgvRA=="],
|
||||
|
||||
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
|
||||
|
||||
|
|
@ -1411,7 +1423,7 @@
|
|||
|
||||
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"svelte": ["svelte@5.18.0", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^1.4.3", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-/Eb81lB8bVUxQPmkPVNBYrU9cZ544+9hE91ZUUXTMf7eWcGW84N1hS3gvv/XsUNOWLLg3IicXP2qa8W3KpTUHA=="],
|
||||
"svelte": ["svelte@5.19.3", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^1.4.3", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-rb/bkYG9jq67OCWikMvaPnfOobyGn0JizVDwHpdeBtLiNXPMcoA9GTFC3BhptP7xGNquUU8J5GiS7PlGlfDAFA=="],
|
||||
|
||||
"svelte-ast-print": ["svelte-ast-print@0.4.2", "", { "dependencies": { "esrap": "1.2.2", "zimmerframe": "1.1.2" }, "peerDependencies": { "svelte": "^5.0.0" } }, "sha512-hRHHufbJoArFmDYQKCpCvc0xUuIEfwYksvyLYEQyH+1xb5LD5sM/IthfooCdXZQtOIqXz6xm7NmaqdfwG4kh6w=="],
|
||||
|
||||
|
|
@ -1447,8 +1459,6 @@
|
|||
|
||||
"throttle-debounce": ["throttle-debounce@5.0.2", "", {}, "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="],
|
||||
|
||||
"tiny-glob": ["tiny-glob@0.2.9", "", { "dependencies": { "globalyzer": "0.1.0", "globrex": "^0.1.2" } }, "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg=="],
|
||||
|
||||
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
|
||||
|
||||
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
|
||||
|
|
@ -1483,9 +1493,9 @@
|
|||
|
||||
"typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.20.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.20.0", "@typescript-eslint/parser": "8.20.0", "@typescript-eslint/utils": "8.20.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-Kxz2QRFsgbWj6Xcftlw3Dd154b3cEPFqQC+qMZrMypSijPd4UanKKvoKDrJ4o8AIfZFKAF+7sMaEIR8mTElozA=="],
|
||||
"typescript-eslint": ["typescript-eslint@8.21.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.21.0", "@typescript-eslint/parser": "8.21.0", "@typescript-eslint/utils": "8.21.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.8.0" } }, "sha512-txEKYY4XMKwPXxNkN8+AxAdX6iIJAPiJbHE/FpQccs/sxw8Lf26kqwC3cn0xkHlW8kEbLhkhCsjWuMveaY9Rxw=="],
|
||||
|
||||
"undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||
|
||||
"universal-github-app-jwt": ["universal-github-app-jwt@1.2.0", "", { "dependencies": { "@types/jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.2" } }, "sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g=="],
|
||||
|
||||
|
|
@ -1513,7 +1523,7 @@
|
|||
|
||||
"value-or-promise": ["value-or-promise@1.0.12", "", {}, "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q=="],
|
||||
|
||||
"vite": ["vite@6.0.7", "", { "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.4.49", "rollup": "^4.23.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ=="],
|
||||
"vite": ["vite@6.0.11", "", { "dependencies": { "esbuild": "^0.24.2", "postcss": "^8.4.49", "rollup": "^4.23.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg=="],
|
||||
|
||||
"vite-node": ["vite-node@2.1.8", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg=="],
|
||||
|
||||
|
|
@ -1547,7 +1557,7 @@
|
|||
|
||||
"xmlbuilder": ["xmlbuilder@13.0.2", "", {}, "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ=="],
|
||||
|
||||
"yaml": ["yaml@2.6.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg=="],
|
||||
"yaml": ["yaml@2.7.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA=="],
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
|
|
@ -1585,6 +1595,8 @@
|
|||
|
||||
"@inlang/paraglide-js/dedent": ["dedent@1.5.1", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg=="],
|
||||
|
||||
"@inlang/paraglide-sveltekit/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
||||
|
||||
"@inlang/paraglide-sveltekit/dedent": ["dedent@1.5.1", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg=="],
|
||||
|
||||
"@inlang/paraglide-sveltekit/devalue": ["devalue@4.3.3", "", {}, "sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg=="],
|
||||
|
|
@ -1627,26 +1639,30 @@
|
|||
|
||||
"@octokit/request-error/@octokit/types": ["@octokit/types@13.7.0", "", { "dependencies": { "@octokit/openapi-types": "^23.0.1" } }, "sha512-BXfRP+3P3IN6fd4uF3SniaHKOO4UXWBfkdR3vA8mIvaoO/wLjGN5qivUtW0QRitBHHMcfC41SLhNVYIZZE+wkA=="],
|
||||
|
||||
"@storybook/blocks/@storybook/csf": ["@storybook/csf@0.1.12", "", { "dependencies": { "type-fest": "^2.19.0" } }, "sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw=="],
|
||||
"@prisma/generator-helper/@prisma/debug": ["@prisma/debug@6.2.1", "", {}, "sha512-0KItvt39CmQxWkEw6oW+RQMD6RZ43SJWgEUnzxN8VC9ixMysa7MzZCZf22LCK5DSooiLNf8vM3LHZm/I/Ni7bQ=="],
|
||||
|
||||
"@storybook/core/@storybook/csf": ["@storybook/csf@0.1.12", "", { "dependencies": { "type-fest": "^2.19.0" } }, "sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw=="],
|
||||
|
||||
"@storybook/test/@storybook/csf": ["@storybook/csf@0.1.12", "", { "dependencies": { "type-fest": "^2.19.0" } }, "sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw=="],
|
||||
"@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="],
|
||||
|
||||
"@tailwindcss/typography/postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
|
||||
|
||||
"@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
|
||||
|
||||
"@testing-library/jest-dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
|
||||
|
||||
"@testing-library/jest-dom/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
|
||||
|
||||
"@testing-library/jest-dom/dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="],
|
||||
|
||||
"@types/react/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"@vitest/expect/@vitest/utils": ["@vitest/utils@2.0.5", "", { "dependencies": { "@vitest/pretty-format": "2.0.5", "estree-walker": "^3.0.3", "loupe": "^3.1.1", "tinyrainbow": "^1.2.0" } }, "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ=="],
|
||||
|
||||
"@vitest/mocker/@vitest/spy": ["@vitest/spy@2.1.8", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg=="],
|
||||
|
||||
"@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||
|
||||
"@whatwg-node/disposablestack/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"@whatwg-node/events/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
|
@ -1657,6 +1673,8 @@
|
|||
|
||||
"ajv-formats/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"ast-types/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"cross-inspect/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
|
@ -1665,8 +1683,6 @@
|
|||
|
||||
"domutils/domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="],
|
||||
|
||||
"dot-case/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@2.1.0", "", {}, "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw=="],
|
||||
|
|
@ -1683,9 +1699,7 @@
|
|||
|
||||
"log-update/slice-ansi": ["slice-ansi@7.1.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg=="],
|
||||
|
||||
"lower-case/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"no-case/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||
|
||||
|
|
@ -1713,7 +1727,7 @@
|
|||
|
||||
"slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"snake-case/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
"solid-js/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
|
|
@ -1745,13 +1759,13 @@
|
|||
|
||||
"terser-webpack-plugin/schema-utils": ["schema-utils@4.3.0", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g=="],
|
||||
|
||||
"vite-node/vite": ["vite@5.4.11", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q=="],
|
||||
"vite-node/vite": ["vite@5.4.14", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA=="],
|
||||
|
||||
"vitest/@vitest/expect": ["@vitest/expect@2.1.8", "", { "dependencies": { "@vitest/spy": "2.1.8", "@vitest/utils": "2.1.8", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" } }, "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw=="],
|
||||
|
||||
"vitest/@vitest/spy": ["@vitest/spy@2.1.8", "", { "dependencies": { "tinyspy": "^3.0.2" } }, "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg=="],
|
||||
|
||||
"vitest/vite": ["vite@5.4.11", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q=="],
|
||||
"vitest/vite": ["vite@5.4.14", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA=="],
|
||||
|
||||
"webpack/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="],
|
||||
|
||||
|
|
@ -1795,6 +1809,8 @@
|
|||
|
||||
"@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@2.0.5", "", { "dependencies": { "tinyrainbow": "^1.2.0" } }, "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ=="],
|
||||
|
||||
"@vitest/expect/@vitest/utils/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||
|
||||
"ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"enquirer/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
|
@ -1855,6 +1871,8 @@
|
|||
|
||||
"sveltedoc-parser/eslint/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"terser-webpack-plugin/schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"vite-node/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||
"nav_greeting": "Hello {name}!",
|
||||
"nav_menu_sms": "SMS",
|
||||
"nav_menu_residents": "Residents",
|
||||
"nav_menu_settings": "Settings",
|
||||
"nav_menu_logout": "Logout",
|
||||
"login_tab_login": "Login",
|
||||
|
|
@ -21,5 +22,20 @@
|
|||
"sms_label_phone": "Phone Number",
|
||||
"sms_label_message": "Message",
|
||||
"sms_button_submit": "Send Message",
|
||||
"residents_title": "Residents",
|
||||
"residents_button_new": "New Resident",
|
||||
"residents_table_edit": "Edit",
|
||||
"residents_modal_title_new": "Create a Resident",
|
||||
"residents_modal_title_edit": "Edit Resident",
|
||||
"residents_modal_submit": "Submit",
|
||||
"residents_modal_delete": "Delete",
|
||||
"residents_modal_label_name": "Name",
|
||||
"residents_modal_label_phone": "Phone Number",
|
||||
"settings_title": "Settings",
|
||||
"settings_category_twilio": "Twilio Config",
|
||||
"settings_twilio_account_sid": "Account SID",
|
||||
"settings_twilio_auth_token": "Auth Token",
|
||||
"settings_twilio_phone_number": "Phone Number",
|
||||
"settings_save": "Save Settings",
|
||||
"error_page_go_home": "Go Home"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
[build]
|
||||
command = "bun run build"
|
||||
publish = "build"
|
||||
29
package.json
29
package.json
|
|
@ -3,16 +3,20 @@
|
|||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prepare": "husky",
|
||||
"postinstall": "prisma generate",
|
||||
"dev": "bun validate-env && bun database:up && bun prisma:generate && vite dev",
|
||||
"build": "vite build",
|
||||
"build-storybook": "storybook build",
|
||||
"database:up": "docker compose -p hestia -f devops/docker-compose.dev.yml up -d && docker compose -p hestia -f devops/docker-compose.dev.yml -f devops/docker-compose.wait.yml run --rm wait -c hestia-database:5432 && bun prisma:push",
|
||||
"database:down": "docker compose -p hestia -f devops/docker-compose.dev.yml down",
|
||||
"docker:build": "docker buildx -t hestia .",
|
||||
"docker:build-storybook": "docker buildx -t hestia-storybook -f Dockerfile.storybook .",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"format": "prettier --write .",
|
||||
"generate-secret": "bun ./scripts/generate-secret.ts",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"test:unit": "vitest",
|
||||
"test": "bun run test:unit -- --run && bun run test:e2e",
|
||||
|
|
@ -25,26 +29,25 @@
|
|||
"prisma:reset": "prisma migrate reset --force",
|
||||
"prisma:studio": "prisma studio",
|
||||
"prisma:validate": "prisma validate",
|
||||
"prepare": "husky",
|
||||
"validate-env": "bun ./scripts/validate-env.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^3.2.2",
|
||||
"@eslint/compat": "^1.2.3",
|
||||
"@playwright/test": "^1.45.3",
|
||||
"@storybook/addon-essentials": "^8.4.7",
|
||||
"@storybook/addon-interactions": "^8.4.7",
|
||||
"@storybook/addon-essentials": "^8.5.0",
|
||||
"@storybook/addon-interactions": "^8.5.0",
|
||||
"@storybook/addon-styling-webpack": "^1.0.1",
|
||||
"@storybook/addon-svelte-csf": "^5.0.0-next.13",
|
||||
"@storybook/addon-themes": "^8.4.7",
|
||||
"@storybook/blocks": "^8.4.7",
|
||||
"@storybook/svelte": "^8.4.7",
|
||||
"@storybook/sveltekit": "^8.4.7",
|
||||
"@storybook/test": "^8.4.7",
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@storybook/addon-themes": "^8.5.0",
|
||||
"@storybook/blocks": "^8.5.0",
|
||||
"@storybook/svelte": "^8.5.0",
|
||||
"@storybook/sveltekit": "^8.5.0",
|
||||
"@storybook/test": "^8.5.0",
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/kit": "^2.15.3",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@types/bun": "^1.1.14",
|
||||
"@types/bun": "^1.1.15",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"daisyui": "^4.12.22",
|
||||
"eslint": "^9.7.0",
|
||||
|
|
@ -56,8 +59,8 @@
|
|||
"prettier": "^3.3.2",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"prisma": "^6.0.1",
|
||||
"storybook": "^8.4.7",
|
||||
"prisma": "6.3.1",
|
||||
"storybook": "^8.5.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwindcss": "^3.4.9",
|
||||
|
|
@ -72,7 +75,7 @@
|
|||
"@inlang/paraglide-sveltekit": "^0.15.0",
|
||||
"@pothos/core": "^4.3.0",
|
||||
"@pothos/plugin-prisma": "^4.4.0",
|
||||
"@prisma/client": "6.0.1",
|
||||
"@prisma/client": "6.3.1",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"clerk-sveltekit": "https://pkg.pr.new/wobsoriano/clerk-sveltekit@ca15d4e",
|
||||
"clsx": "^2.1.1",
|
||||
|
|
|
|||
34
prisma/migrations/20250127041354_tenant_config/migration.sql
Normal file
34
prisma/migrations/20250127041354_tenant_config/migration.sql
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "TenantConfig" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "TenantConfig_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "TwilioConfig" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantConfigId" TEXT NOT NULL,
|
||||
"accountSID" TEXT NOT NULL,
|
||||
"authToken" TEXT NOT NULL,
|
||||
"phoneNumber" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "TwilioConfig_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "TenantConfig_tenantId_key" ON "TenantConfig"("tenantId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "TwilioConfig_tenantConfigId_key" ON "TwilioConfig"("tenantConfigId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TenantConfig" ADD CONSTRAINT "TenantConfig_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "TwilioConfig" ADD CONSTRAINT "TwilioConfig_tenantConfigId_fkey" FOREIGN KEY ("tenantConfigId") REFERENCES "TenantConfig"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
14
prisma/migrations/20250206142847_add_residents/migration.sql
Normal file
14
prisma/migrations/20250206142847_add_residents/migration.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Resident" (
|
||||
"id" TEXT NOT NULL,
|
||||
"tenantId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"phoneNumber" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Resident_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Resident" ADD CONSTRAINT "Resident_tenantId_fkey" FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
|
|
@ -10,8 +10,9 @@ generator pothos {
|
|||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
directUrl = env("DIRECT_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
|
|
@ -30,12 +31,53 @@ model User {
|
|||
@@unique([clerkId, tenantId])
|
||||
}
|
||||
|
||||
model Tenant {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
clerkOrganizationId String @unique
|
||||
users User[]
|
||||
model Resident {
|
||||
id String @id @default(uuid())
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
tenantId String
|
||||
|
||||
name String
|
||||
phoneNumber String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Tenant {
|
||||
id String @id @default(uuid())
|
||||
clerkOrganizationId String @unique
|
||||
|
||||
users User[]
|
||||
residents Resident[]
|
||||
tenantConfig TenantConfig?
|
||||
|
||||
name String
|
||||
slug String @unique
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model TenantConfig {
|
||||
id String @id @default(uuid())
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id])
|
||||
tenantId String @unique
|
||||
|
||||
twilioConfig TwilioConfig?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model TwilioConfig {
|
||||
id String @id @default(uuid())
|
||||
tenantConfig TenantConfig @relation(fields: [tenantConfigId], references: [id])
|
||||
tenantConfigId String @unique
|
||||
|
||||
accountSID String
|
||||
authToken String
|
||||
phoneNumber String
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
6
scripts/generate-secret.ts
Normal file
6
scripts/generate-secret.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { randomBytes } from 'node:crypto';
|
||||
|
||||
console.log('SECRET: ', {
|
||||
password: randomBytes(16).toString('hex'),
|
||||
salt: randomBytes(16).toString('hex'),
|
||||
});
|
||||
|
|
@ -1,12 +1,26 @@
|
|||
import { PhoneRegex } from '../src/lib/regex/phone';
|
||||
import { z } from 'zod';
|
||||
|
||||
const ValidateEnvironment = () => {
|
||||
const { success, error } = z
|
||||
.object({
|
||||
TWILIO_ACCOUNT_SID: z.string().min(1),
|
||||
TWILIO_AUTH_TOKEN: z.string().min(1),
|
||||
TWILIO_PHONE_NUMBER: z.string().regex(PhoneRegex),
|
||||
SECRETS_PASSWORD: z.string().length(32),
|
||||
SECRETS_SALT: z.string().min(16),
|
||||
SECRETS_IV_POSITION: z.string().transform((val, ctx) => {
|
||||
const parsed = parseInt(val);
|
||||
if (isNaN(parsed)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Not a number',
|
||||
});
|
||||
|
||||
// This is a special symbol you can use to
|
||||
// return early from the transform function.
|
||||
// It has type `never` so it does not affect the
|
||||
// inferred return type.
|
||||
return z.NEVER;
|
||||
}
|
||||
return parsed;
|
||||
}),
|
||||
})
|
||||
.safeParse(process.env);
|
||||
|
||||
|
|
|
|||
4
src/app.d.ts
vendored
4
src/app.d.ts
vendored
|
|
@ -1,5 +1,7 @@
|
|||
// See https://svelte.dev/docs/kit/types#app.d.ts
|
||||
|
||||
import type { Tenant, User } from '@prisma/client';
|
||||
|
||||
// for information about these interfaces
|
||||
declare global {
|
||||
namespace App {
|
||||
|
|
@ -10,6 +12,8 @@ declare global {
|
|||
orgId?: string | null;
|
||||
sessionId?: string;
|
||||
};
|
||||
user: User;
|
||||
tenant: Tenant;
|
||||
}
|
||||
// interface PageData {}
|
||||
// interface PageState {}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { validateSession } from '$lib/server/middleware';
|
||||
import { sequence } from '@sveltejs/kit/hooks';
|
||||
import { withClerkHandler } from 'clerk-sveltekit/server';
|
||||
|
||||
export const handle = withClerkHandler();
|
||||
export const handle = sequence(withClerkHandler(), validateSession());
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
children,
|
||||
class: className,
|
||||
color,
|
||||
disabled,
|
||||
full = false,
|
||||
glass = false,
|
||||
shape,
|
||||
|
|
@ -37,7 +36,6 @@
|
|||
|
||||
<button
|
||||
{...props}
|
||||
{disabled}
|
||||
class={twMerge('btn', clsx(className))}
|
||||
class:btn-active={active}
|
||||
class:no-animation={!animation}
|
||||
|
|
@ -51,7 +49,7 @@
|
|||
class:btn-success={color === 'success'}
|
||||
class:btn-warning={color === 'warning'}
|
||||
class:btn-error={color === 'error'}
|
||||
class:btn-disabled={disabled}
|
||||
class:btn-disabled={props.disabled}
|
||||
class:w-full={full}
|
||||
class:glass
|
||||
class:btn-circle={shape === 'circle'}
|
||||
|
|
|
|||
36
src/lib/components/Actions/Modal/Modal.stories.svelte
Normal file
36
src/lib/components/Actions/Modal/Modal.stories.svelte
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<script module lang="ts">
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import Modal from './Modal.svelte';
|
||||
import ModalBody from './ModalBody.svelte';
|
||||
import ModalActions from './ModalActions.svelte';
|
||||
import Button from '../Button.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Actions/Modal',
|
||||
component: Modal,
|
||||
argTypes: {
|
||||
open: {
|
||||
control: 'boolean',
|
||||
defaultValue: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
let dialog: HTMLDialogElement | undefined = $state(undefined);
|
||||
</script>
|
||||
|
||||
{#snippet template({ children: _, ...props }: Partial<ComponentProps<typeof Modal>>)}
|
||||
<Button onclick={() => dialog?.showModal()}>Open</Button>
|
||||
<Modal {...props} backdrop bind:dialog>
|
||||
<ModalBody>
|
||||
<h3 class="text-lg font-bold">Hello!</h3>
|
||||
<p class="py-4">Press ESC key or click the button below to close</p>
|
||||
<ModalActions>
|
||||
<Button onclick={() => dialog?.close()}>Close</Button>
|
||||
</ModalActions>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
{/snippet}
|
||||
|
||||
<Story name="Default" children={template} />
|
||||
21
src/lib/components/Actions/Modal/Modal.svelte
Normal file
21
src/lib/components/Actions/Modal/Modal.svelte
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts">
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = SvelteHTMLElements['dialog'] & {
|
||||
backdrop?: boolean;
|
||||
dialog?: HTMLDialogElement;
|
||||
};
|
||||
|
||||
let { backdrop, dialog = $bindable(), children, class: className, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
<dialog {...props} class={twMerge('modal', clsx(className))} bind:this={dialog}>
|
||||
{@render children?.()}
|
||||
{#if backdrop}
|
||||
<form method="dialog" class="modal-backdrop">
|
||||
<button>close</button>
|
||||
</form>
|
||||
{/if}
|
||||
</dialog>
|
||||
13
src/lib/components/Actions/Modal/ModalActions.svelte
Normal file
13
src/lib/components/Actions/Modal/ModalActions.svelte
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts">
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = SvelteHTMLElements['div'];
|
||||
|
||||
let { children, class: className, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div {...props} class={twMerge('modal-action', clsx(className))}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
13
src/lib/components/Actions/Modal/ModalBody.svelte
Normal file
13
src/lib/components/Actions/Modal/ModalBody.svelte
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts">
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = SvelteHTMLElements['div'];
|
||||
|
||||
let { children, class: className, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div {...props} class={twMerge('modal-box', clsx(className))}>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
3
src/lib/components/Actions/Modal/index.ts
Normal file
3
src/lib/components/Actions/Modal/index.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export { default as Modal } from './Modal.svelte';
|
||||
export { default as ModalActions } from './ModalActions.svelte';
|
||||
export { default as ModalBody } from './ModalBody.svelte';
|
||||
|
|
@ -1 +1,2 @@
|
|||
export { default as Button } from './Button.svelte';
|
||||
export * from './Modal/';
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<label class="form-control w-full" transition:fadeTransition={{ duration: fade ? 200 : 0 }}>
|
||||
<div class="label">
|
||||
<span
|
||||
class="label-text"
|
||||
class="label-text flex items-center gap-2"
|
||||
class:text-primary={color === 'primary'}
|
||||
class:text-secondary={color === 'secondary'}
|
||||
class:text-accent={color === 'accent'}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,34 @@
|
|||
<script lang="ts">
|
||||
import type { DaisyColor, DaisySize } from '$lib/types';
|
||||
import clsx from 'clsx';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
bordered?: boolean;
|
||||
color?: Omit<DaisyColor, 'neutral'>;
|
||||
disabled?: boolean;
|
||||
error?: string | Snippet;
|
||||
form?: string;
|
||||
label?: string | Snippet;
|
||||
name?: string;
|
||||
placeholder?: string;
|
||||
size?: DaisySize;
|
||||
};
|
||||
let { bordered, color, error, label, size, ...props }: Props = $props();
|
||||
resizable?: boolean | 'yes' | 'no' | 'x' | 'y';
|
||||
size?: DaisySize | 'md';
|
||||
} & SvelteHTMLElements['textarea'];
|
||||
let {
|
||||
bordered,
|
||||
class: className,
|
||||
color,
|
||||
error,
|
||||
label,
|
||||
resizable,
|
||||
size,
|
||||
...props
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<label class="form-control w-full max-w-lg">
|
||||
<label class="form-control w-full">
|
||||
<div class="label">
|
||||
<span
|
||||
class="label-text"
|
||||
class="label-text flex items-center gap-2"
|
||||
class:text-primary={color === 'primary'}
|
||||
class:text-secondary={color === 'secondary'}
|
||||
class:text-accent={color === 'accent'}
|
||||
|
|
@ -43,7 +52,8 @@
|
|||
</span>
|
||||
</div>
|
||||
<textarea
|
||||
class="textarea"
|
||||
{...props}
|
||||
class={twMerge('textarea', clsx(className))}
|
||||
class:textarea-bordered={bordered}
|
||||
class:textarea-xs={size === 'xs'}
|
||||
class:textarea-sm={size === 'sm'}
|
||||
|
|
@ -56,6 +66,9 @@
|
|||
class:textarea-success={color === 'success'}
|
||||
class:textarea-warning={color === 'warning'}
|
||||
class:textarea-error={color === 'error' || error}
|
||||
{...props}
|
||||
class:resize={resizable === true || resizable === 'yes'}
|
||||
class:resize-x={resizable === 'x'}
|
||||
class:resize-y={resizable === 'y'}
|
||||
class:resize-none={resizable === false || resizable === 'no'}
|
||||
></textarea>
|
||||
</label>
|
||||
|
|
|
|||
51
src/lib/components/Datadisplay/Avatar.stories.svelte
Normal file
51
src/lib/components/Datadisplay/Avatar.stories.svelte
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<script module lang="ts">
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import Avatar from './Avatar.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Data display/Avatar',
|
||||
component: Avatar,
|
||||
argTypes: {
|
||||
img: {
|
||||
control: 'text',
|
||||
},
|
||||
placeholder: {
|
||||
control: 'text',
|
||||
defaultValue: 'DP',
|
||||
},
|
||||
presence: {
|
||||
control: 'select',
|
||||
options: [undefined, 'online', 'offline'],
|
||||
},
|
||||
ring: {
|
||||
control: 'select',
|
||||
options: [
|
||||
undefined,
|
||||
'neutral',
|
||||
'primary',
|
||||
'secondary',
|
||||
'accent',
|
||||
'info',
|
||||
'success',
|
||||
'warning',
|
||||
'error',
|
||||
],
|
||||
},
|
||||
shape: {
|
||||
control: 'select',
|
||||
options: ['square', 'circle'],
|
||||
},
|
||||
size: {
|
||||
control: 'select',
|
||||
options: ['xs', 'sm', 'md', 'lg'],
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<Story
|
||||
name="Default"
|
||||
args={{
|
||||
img: 'https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp',
|
||||
}}
|
||||
/>
|
||||
62
src/lib/components/Datadisplay/Avatar.svelte
Normal file
62
src/lib/components/Datadisplay/Avatar.svelte
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<script lang="ts">
|
||||
import type { DaisyColor, DaisySize } from '$lib/types';
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
img?: string;
|
||||
placeholder: string;
|
||||
presence?: 'online' | 'offline';
|
||||
ring?: Exclude<DaisyColor, 'ghost'>;
|
||||
shape?: 'square' | 'circle';
|
||||
size?: DaisySize | 'md';
|
||||
} & Omit<SvelteHTMLElements['div'], 'children'>;
|
||||
|
||||
let {
|
||||
class: className,
|
||||
img,
|
||||
placeholder,
|
||||
presence,
|
||||
ring,
|
||||
shape = 'circle',
|
||||
size = 'md',
|
||||
...props
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<div {...props} class={twMerge('avatar', presence, clsx(className))} class:placeholder>
|
||||
<div
|
||||
class={twMerge(
|
||||
'rounded-xl',
|
||||
clsx({
|
||||
'rounded-xl': shape === 'square',
|
||||
'rounded-full': shape === 'circle',
|
||||
'w-12': size === 'xs',
|
||||
'w-16': size === 'sm',
|
||||
'w-20': size === 'md',
|
||||
'w-32': size === 'lg',
|
||||
'avatar-ring ring ring-offset-2 ring-offset-base-100': !!ring,
|
||||
})
|
||||
)}
|
||||
class:bg-neutral={placeholder}
|
||||
class:ring-neutral={ring === 'neutral'}
|
||||
class:ring-primary={ring === 'primary'}
|
||||
class:ring-secondary={ring === 'secondary'}
|
||||
class:ring-accent={ring === 'accent'}
|
||||
class:ring-info={ring === 'info'}
|
||||
class:ring-success={ring === 'success'}
|
||||
class:ring-warning={ring === 'warning'}
|
||||
class:ring-error={ring === 'error'}
|
||||
>
|
||||
{#if img}
|
||||
<img src={img} alt={placeholder} />
|
||||
{:else}
|
||||
<span
|
||||
class:text-3xl={size === 'lg'}
|
||||
class:text-xl={size === 'md'}
|
||||
class:text-xs={size === 'xs'}>{placeholder}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
1
src/lib/components/Datadisplay/index.ts
Normal file
1
src/lib/components/Datadisplay/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as Avatar } from './Avatar.svelte';
|
||||
|
|
@ -1,19 +1,23 @@
|
|||
<script lang="ts">
|
||||
import type { DaisyColor } from '$lib/types';
|
||||
import clsx from 'clsx';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
children?: Snippet;
|
||||
icon?: Snippet;
|
||||
status?: Extract<DaisyColor, 'info' | 'success' | 'warning' | 'error'>;
|
||||
};
|
||||
} & SvelteHTMLElements['div'];
|
||||
|
||||
let { children, icon, status: color }: Props = $props();
|
||||
let { children, class: className, icon, status: color, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div
|
||||
{...props}
|
||||
role="alert"
|
||||
class="alert"
|
||||
class={twMerge('alert', clsx(className))}
|
||||
class:alert-info={color === 'info'}
|
||||
class:alert-success={color === 'success'}
|
||||
class:alert-warning={color === 'warning'}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
<script lang="ts">
|
||||
import type { DaisyColor, DaisySize } from '$lib/types';
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
color?: Exclude<DaisyColor, 'ghost'>;
|
||||
size?: DaisySize | 'md';
|
||||
variant?: 'spinner' | 'dots' | 'ring' | 'ball' | 'bars' | 'infinity';
|
||||
};
|
||||
let { color, size = 'md', variant = 'spinner' }: Props = $props();
|
||||
} & Pick<SvelteHTMLElements['span'], 'class'>;
|
||||
let { class: className, color, size = 'md', variant = 'spinner' }: Props = $props();
|
||||
</script>
|
||||
|
||||
<span
|
||||
class="loading"
|
||||
class={twMerge('loading', clsx(className))}
|
||||
class:text-primary={color === 'primary'}
|
||||
class:text-secondary={color === 'secondary'}
|
||||
class:text-accent={color === 'accent'}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
</script>
|
||||
|
||||
<progress
|
||||
{...props}
|
||||
class={twMerge('progress', clsx(className))}
|
||||
class:progress-primary={color === 'primary'}
|
||||
class:progress-secondary={color === 'secondary'}
|
||||
|
|
@ -19,7 +20,6 @@
|
|||
class:progress-success={color === 'success'}
|
||||
class:progress-warning={color === 'warning'}
|
||||
class:progress-error={color === 'error'}
|
||||
{...props}
|
||||
>
|
||||
{@render children?.()}
|
||||
</progress>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
<script lang="ts">
|
||||
import clsx from 'clsx';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
children?: Snippet;
|
||||
} & SvelteHTMLElements['div'];
|
||||
type Props = SvelteHTMLElements['div'];
|
||||
let { children, class: className, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
{...props}
|
||||
class={twMerge('tooltip', clsx(className))}
|
||||
class:tooltip-primary={color === 'primary'}
|
||||
class:tooltip-secondary={color === 'secondary'}
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
class:tooltip-left={position === 'left'}
|
||||
class:tooltip-right={position === 'right'}
|
||||
data-tip={tip}
|
||||
{...props}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
{...props}
|
||||
class={twMerge('divider', clsx(className))}
|
||||
class:divider-neutral={color === 'neutral'}
|
||||
class:divider-primary={color === 'primary'}
|
||||
|
|
@ -26,7 +27,6 @@
|
|||
class:divider-vertical={direction === 'vertical'}
|
||||
class:divider-start={variant === 'start'}
|
||||
class:divider-end={variant === 'end'}
|
||||
{...props}
|
||||
>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
</script>
|
||||
|
||||
<a
|
||||
{...props}
|
||||
class={twMerge('link', clsx(className))}
|
||||
class:link-primary={color === 'primary'}
|
||||
class:link-secondary={color === 'secondary'}
|
||||
|
|
@ -19,6 +20,5 @@
|
|||
class:link-success={color === 'success'}
|
||||
class:link-warning={color === 'warning'}
|
||||
class:link-error={color === 'error'}
|
||||
class:link-hover={hover}
|
||||
{...props}>{@render children?.()}</a
|
||||
class:link-hover={hover}>{@render children?.()}</a
|
||||
>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
let { start, center, end }: { start?: Snippet; center?: Snippet; end?: Snippet } = $props();
|
||||
</script>
|
||||
|
||||
<header class="navbar justify-between bg-base-200 px-4">
|
||||
<header class="navbar justify-between rounded-box bg-base-200 px-4">
|
||||
<div class="navbar-start">{@render start?.()}</div>
|
||||
<div class="navbar-center">{@render center?.()}</div>
|
||||
<div class="navbar-end">{@render end?.()}</div>
|
||||
|
|
|
|||
28
src/lib/components/Residents/ResidentTable.stories.svelte
Normal file
28
src/lib/components/Residents/ResidentTable.stories.svelte
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<script module lang="ts">
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import type { ComponentProps } from 'svelte';
|
||||
import ResidentTable from './ResidentTable.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Residents/Resident Table',
|
||||
component: ResidentTable,
|
||||
});
|
||||
</script>
|
||||
|
||||
{#snippet template(props: ComponentProps<typeof ResidentTable>)}
|
||||
<ResidentTable {...props} />
|
||||
{/snippet}
|
||||
|
||||
<Story
|
||||
name="Default"
|
||||
children={template}
|
||||
args={{
|
||||
items: [
|
||||
{
|
||||
id: '99fc03e9-3ed1-4047-b9ad-0bf2a9025eaa',
|
||||
name: 'Resident 1',
|
||||
phoneNumber: '111-1111',
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
53
src/lib/components/Residents/ResidentTable.svelte
Normal file
53
src/lib/components/Residents/ResidentTable.svelte
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<script lang="ts" module>
|
||||
export type ResidentItem = Pick<Resident, 'id' | 'name' | 'phoneNumber'>;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type { Resident } from '@prisma/client';
|
||||
import clsx from 'clsx';
|
||||
import { UserRoundPen } from 'lucide-svelte';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import Button from '../Actions/Button.svelte';
|
||||
import { messages } from '$lib/i18n';
|
||||
|
||||
type Props = {
|
||||
items?: ResidentItem[];
|
||||
onEdit?: (resident: ResidentItem) => void;
|
||||
} & Omit<SvelteHTMLElements['table'], 'children'>;
|
||||
|
||||
let { items, onEdit, class: className, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
<table {...props} class={twMerge('table', clsx(className))}>
|
||||
<!-- head -->
|
||||
<thead>
|
||||
<tr class="bg-base-100">
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Phone Number</th>
|
||||
{#if onEdit}
|
||||
<th class="flex justify-end"><UserRoundPen class="mx-3" /></th>
|
||||
{/if}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- items -->
|
||||
{#if items}
|
||||
{#each items as resident, index (resident.id)}
|
||||
<tr class="hover">
|
||||
<th>{index + 1}</th>
|
||||
<td>{resident.name}</td>
|
||||
<td>{resident.phoneNumber}</td>
|
||||
{#if onEdit}
|
||||
<td class="text-end">
|
||||
<Button size="sm" color="accent" onclick={() => onEdit(resident)}>
|
||||
{messages.residents_table_edit()}
|
||||
</Button>
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
{/each}
|
||||
{/if}
|
||||
</tbody>
|
||||
</table>
|
||||
2
src/lib/components/Residents/index.ts
Normal file
2
src/lib/components/Residents/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export { default as ResidentTable } from './ResidentTable.svelte';
|
||||
export * from './ResidentTable.svelte';
|
||||
64
src/lib/components/SMS/RecipientList.svelte
Normal file
64
src/lib/components/SMS/RecipientList.svelte
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<script lang="ts" module>
|
||||
export type Recipient = {
|
||||
id: string;
|
||||
name: string;
|
||||
phone: string;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import clsx from 'clsx';
|
||||
import type { SvelteHTMLElements } from 'svelte/elements';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
recipients: Recipient[];
|
||||
selected: Recipient[];
|
||||
} & Omit<SvelteHTMLElements['table'], 'children'>;
|
||||
|
||||
let { recipients, selected = $bindable([]), class: className, ...props }: Props = $props();
|
||||
|
||||
let checked = $state(recipients.map(() => false));
|
||||
|
||||
$effect(() => {
|
||||
selected = checked
|
||||
.entries()
|
||||
.filter(([, val]) => val)
|
||||
.map(([index]) => recipients[index])
|
||||
.toArray();
|
||||
});
|
||||
</script>
|
||||
|
||||
<table {...props} class={twMerge('table', clsx(className))}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<input
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
onchange={({ currentTarget }) => {
|
||||
checked = checked.map(() => currentTarget.checked);
|
||||
}}
|
||||
/>
|
||||
</th>
|
||||
<th> Name </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each recipients as resident, index}
|
||||
<tr>
|
||||
<th
|
||||
><input
|
||||
class="checkbox"
|
||||
type="checkbox"
|
||||
checked={checked[index]}
|
||||
onchange={({ currentTarget }) => {
|
||||
checked[index] = currentTarget.checked;
|
||||
}}
|
||||
/></th
|
||||
>
|
||||
<td>{resident.name}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
2
src/lib/components/SMS/index.ts
Normal file
2
src/lib/components/SMS/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from './RecipientList.svelte';
|
||||
export { default as RecipientList } from './RecipientList.svelte';
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
import { redirect, type ServerLoadEvent } from '@sveltejs/kit';
|
||||
import { prisma } from '../prisma';
|
||||
import { createClerkClient } from '@clerk/backend';
|
||||
import { CLERK_SECRET_KEY } from '$env/static/private';
|
||||
import { clerkClient } from 'clerk-sveltekit/server';
|
||||
import { logger } from '$lib/server/logger';
|
||||
|
||||
const clerkSessionClient = createClerkClient({
|
||||
secretKey: CLERK_SECRET_KEY,
|
||||
});
|
||||
|
||||
export async function validateSession({ locals }: ServerLoadEvent) {
|
||||
if (!locals.auth.userId || !locals.auth.sessionId) {
|
||||
return redirect(307, '/login');
|
||||
}
|
||||
|
||||
if ((!locals.auth.orgId && locals.auth.sessionId) || !locals.auth.orgId) {
|
||||
// Sign out the user if they are not associated with an organization
|
||||
await clerkSessionClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
return redirect(307, '/login');
|
||||
}
|
||||
|
||||
const clerkUser = await clerkClient.users.getUser(locals.auth.userId);
|
||||
|
||||
const tenantClerkId = locals.auth.orgId;
|
||||
|
||||
let tenant = await prisma.tenant.findUnique({
|
||||
where: {
|
||||
clerkOrganizationId: tenantClerkId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!tenant) {
|
||||
const organization = await clerkClient.organizations.getOrganization({
|
||||
organizationId: tenantClerkId,
|
||||
});
|
||||
|
||||
tenant = await prisma.tenant.create({
|
||||
data: {
|
||||
clerkOrganizationId: tenantClerkId,
|
||||
name: organization.name,
|
||||
slug: organization.slug ?? `tenant-${tenantClerkId}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let user = await prisma.user.findFirst({
|
||||
where: {
|
||||
clerkId: clerkUser.id,
|
||||
tenantId: tenant.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
if (clerkUser.emailAddresses.length === 0) {
|
||||
logger.error('User has no email address');
|
||||
await clerkSessionClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
|
||||
return redirect(307, '/login');
|
||||
}
|
||||
|
||||
user = await prisma.user.create({
|
||||
data: {
|
||||
clerkId: clerkUser.id,
|
||||
email: clerkUser.emailAddresses[0].emailAddress,
|
||||
name: clerkUser.fullName ?? '',
|
||||
tenantId: tenant.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (clerkUser.fullName === null) {
|
||||
logger.error('User has no name');
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
user: { name: user.name, hasImage: clerkUser.hasImage, imageUrl: clerkUser.imageUrl },
|
||||
};
|
||||
}
|
||||
20
src/lib/server/crypto/encryption.test.ts
Normal file
20
src/lib/server/crypto/encryption.test.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { decrypt, encrypt } from './encryption';
|
||||
|
||||
describe('Encryption', () => {
|
||||
it('should encrypt and decrypt data', () => {
|
||||
const data = 'aye its ya boi!';
|
||||
|
||||
vi.mock('$env/static/private', () => ({
|
||||
SECRETS_PASSWORD: 'aac7405eb3384e68c285fc252dbf68b2',
|
||||
SECRETS_SALT: 'c4aeaf8bda72ea45e8c23269ca849013',
|
||||
SECRETS_IV_POSITION: 9,
|
||||
}));
|
||||
|
||||
const encrypted = encrypt(data);
|
||||
console.log(encrypted);
|
||||
const decrypted = decrypt(encrypted);
|
||||
|
||||
expect(decrypted).toEqual(data);
|
||||
});
|
||||
});
|
||||
39
src/lib/server/crypto/encryption.ts
Normal file
39
src/lib/server/crypto/encryption.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { SECRETS_PASSWORD, SECRETS_IV_POSITION, SECRETS_SALT } from '$env/static/private';
|
||||
import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto';
|
||||
|
||||
const algorithm = 'aes-256-gcm';
|
||||
const password = SECRETS_PASSWORD;
|
||||
const salt = SECRETS_SALT;
|
||||
const iv_position = Number(SECRETS_IV_POSITION);
|
||||
|
||||
function construct(encrypted: string, tag: Buffer, iv: { value: Buffer; position: number }) {
|
||||
return `${encrypted.slice(0, iv.position)}${iv.value.toString('hex')}${encrypted.slice(iv.position)}${tag.toString('hex')}`;
|
||||
}
|
||||
|
||||
function deconstruct(encrypted: string, position: number): [Buffer, string, Buffer] {
|
||||
const iv = encrypted.slice(position, position + 16);
|
||||
const text = `${encrypted.slice(0, position)}${encrypted.slice(position + 16, encrypted.length - 32)}`;
|
||||
const authTag = encrypted.slice(encrypted.length - 32);
|
||||
return [Buffer.from(iv, 'hex'), text, Buffer.from(authTag, 'hex')];
|
||||
}
|
||||
|
||||
export function encrypt(value: string): string {
|
||||
const key = scryptSync(password, salt, 32);
|
||||
const iv = randomBytes(8);
|
||||
|
||||
const cipher = createCipheriv(algorithm, key, iv);
|
||||
const encrypted = cipher.update(value, 'utf-8', 'hex') + cipher.final('hex');
|
||||
const authTag = cipher.getAuthTag();
|
||||
|
||||
return construct(encrypted, authTag, { value: iv, position: iv_position });
|
||||
}
|
||||
|
||||
export function decrypt(value: string): string {
|
||||
const key = scryptSync(password, salt, 32);
|
||||
const [iv, text, authTag] = deconstruct(value, iv_position);
|
||||
|
||||
const decipher = createDecipheriv(algorithm, key, iv);
|
||||
decipher.setAuthTag(authTag);
|
||||
|
||||
return decipher.update(text, 'hex', 'utf-8') + decipher.final('utf-8');
|
||||
}
|
||||
1
src/lib/server/crypto/index.ts
Normal file
1
src/lib/server/crypto/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './encryption';
|
||||
1
src/lib/server/middleware/index.ts
Normal file
1
src/lib/server/middleware/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './server';
|
||||
1
src/lib/server/middleware/server/index.ts
Normal file
1
src/lib/server/middleware/server/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './validateSession';
|
||||
105
src/lib/server/middleware/server/validateSession.ts
Normal file
105
src/lib/server/middleware/server/validateSession.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { logger } from '$lib/server/logger';
|
||||
import { prisma } from '$lib/server/prisma';
|
||||
import { type Handle } from '@sveltejs/kit';
|
||||
import { clerkClient } from 'clerk-sveltekit/server';
|
||||
|
||||
const publicRoutes = ['/login'];
|
||||
|
||||
const loginRedirect = () =>
|
||||
new Response(null, {
|
||||
status: 307,
|
||||
headers: {
|
||||
location: '/login',
|
||||
},
|
||||
});
|
||||
|
||||
async function findOrCreateTenant(tenantClerkId: string) {
|
||||
const tenant = await prisma.tenant.findUnique({
|
||||
where: {
|
||||
clerkOrganizationId: tenantClerkId,
|
||||
},
|
||||
});
|
||||
|
||||
if (tenant) {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
const organization = await clerkClient.organizations.getOrganization({
|
||||
organizationId: tenantClerkId,
|
||||
});
|
||||
|
||||
return await prisma.tenant.create({
|
||||
data: {
|
||||
clerkOrganizationId: tenantClerkId,
|
||||
name: organization.name,
|
||||
slug: organization.slug ?? `tenant-${tenantClerkId}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function validateSession(): Handle {
|
||||
return async ({ event: { locals, url, ...rest }, resolve }) => {
|
||||
// Public route? LET THEM PASS!
|
||||
if (url !== null && publicRoutes.includes(url.pathname)) {
|
||||
return resolve({ locals, url, ...rest });
|
||||
}
|
||||
|
||||
// No session, redirect!
|
||||
if (!locals.auth.sessionId) {
|
||||
return loginRedirect();
|
||||
}
|
||||
|
||||
// No user, revoke session and redirect!
|
||||
if (!locals.auth.userId) {
|
||||
await clerkClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
return loginRedirect();
|
||||
}
|
||||
|
||||
// No org, signout and redirect!
|
||||
if (!locals.auth.orgId) {
|
||||
await clerkClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
return loginRedirect();
|
||||
}
|
||||
|
||||
// Make sure that a tenant exists for the clerk org
|
||||
const tenant = await findOrCreateTenant(locals.auth.orgId);
|
||||
|
||||
// Make sure a user exists for the clerk user
|
||||
const clerkUser = await clerkClient.users.getUser(locals.auth.userId);
|
||||
|
||||
let user = await prisma.user.findFirst({
|
||||
where: {
|
||||
clerkId: clerkUser.id,
|
||||
tenantId: tenant.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
if (clerkUser.emailAddresses.length === 0) {
|
||||
logger.error('User has no email address');
|
||||
await clerkClient.sessions.revokeSession(locals.auth.sessionId);
|
||||
|
||||
return loginRedirect();
|
||||
}
|
||||
|
||||
user = await prisma.user.create({
|
||||
data: {
|
||||
clerkId: clerkUser.id,
|
||||
email: clerkUser.emailAddresses[0].emailAddress,
|
||||
name: clerkUser.fullName ?? '',
|
||||
tenantId: tenant.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (clerkUser.fullName === null) {
|
||||
logger.warn(`User {${user.id}} has no name!`);
|
||||
}
|
||||
}
|
||||
|
||||
// Load user and tenant into locals
|
||||
locals.user = user;
|
||||
locals.tenant = tenant;
|
||||
|
||||
return resolve({ locals, url, ...rest });
|
||||
};
|
||||
}
|
||||
|
|
@ -1,3 +1,17 @@
|
|||
import { PrismaClient } from '@prisma/client';
|
||||
import { logger } from '../logger';
|
||||
|
||||
export const prisma = new PrismaClient();
|
||||
export const prisma = new PrismaClient({
|
||||
log: [
|
||||
{ emit: 'event', level: 'query' },
|
||||
{ emit: 'event', level: 'info' },
|
||||
],
|
||||
});
|
||||
|
||||
prisma.$on('query', (event) => {
|
||||
logger.debug(`Query [${event.duration}ms]: ${event.query}`);
|
||||
});
|
||||
|
||||
prisma.$on('info', (event) => {
|
||||
logger.info(event.message);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
import { TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN } from '$env/static/private';
|
||||
import twilio from 'twilio';
|
||||
|
||||
export const TwilioClient = twilio(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
|
||||
|
|
@ -1 +1,20 @@
|
|||
export * from './client';
|
||||
import type { TwilioConfig } from '@prisma/client';
|
||||
import { decrypt, encrypt } from '../crypto';
|
||||
|
||||
type TwilioCore = Pick<TwilioConfig, 'accountSID' | 'authToken' | 'phoneNumber'>;
|
||||
|
||||
export function encryptTwilioConfig({ accountSID, authToken, phoneNumber }: TwilioCore) {
|
||||
return {
|
||||
accountSID: encrypt(accountSID),
|
||||
authToken: encrypt(authToken),
|
||||
phoneNumber: encrypt(phoneNumber),
|
||||
};
|
||||
}
|
||||
|
||||
export function decryptTwilioConfig({ accountSID, authToken, phoneNumber }: TwilioCore) {
|
||||
return {
|
||||
accountSID: decrypt(accountSID),
|
||||
authToken: decrypt(authToken),
|
||||
phoneNumber: decrypt(phoneNumber),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@
|
|||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="layout">
|
||||
<ParaglideJS {i18n}>
|
||||
<ClerkProvider publishableKey={PUBLIC_CLERK_PUBLISHABLE_KEY}>
|
||||
<ParaglideJS {i18n}>
|
||||
<ClerkProvider publishableKey={PUBLIC_CLERK_PUBLISHABLE_KEY}>
|
||||
<div class="layout">
|
||||
{@render children()}
|
||||
</ClerkProvider>
|
||||
</ParaglideJS>
|
||||
</div>
|
||||
</div>
|
||||
</ClerkProvider>
|
||||
</ParaglideJS>
|
||||
|
||||
<style>
|
||||
.layout {
|
||||
@apply h-screen w-screen bg-base-100;
|
||||
@apply h-screen w-screen p-8;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
import { validateSession } from '$lib/server/auth';
|
||||
|
||||
export const load = async (event) => validateSession(event);
|
||||
|
|
@ -1,3 +1,13 @@
|
|||
import { validateSession } from '$lib/server/auth';
|
||||
import { clerkClient } from 'clerk-sveltekit/server';
|
||||
|
||||
export const load = async (event) => validateSession(event);
|
||||
export const load = async ({ locals }) => {
|
||||
const clerkUser = await clerkClient.users.getUser(locals.auth.userId!);
|
||||
|
||||
return {
|
||||
user: {
|
||||
name: clerkUser.fullName || '',
|
||||
hasImage: clerkUser.hasImage,
|
||||
imageUrl: clerkUser.imageUrl,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,17 +5,15 @@
|
|||
import { messages } from '$lib/i18n';
|
||||
import 'clerk-sveltekit/client';
|
||||
import SignOutButton from 'clerk-sveltekit/client/SignOutButton.svelte';
|
||||
import { LogOut, MessageCircleMore } from 'lucide-svelte';
|
||||
import { Cog, LogOut, Menu, MessageCircleMore, UsersRound } from 'lucide-svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
type Props = {
|
||||
children: Snippet;
|
||||
data: PageData;
|
||||
};
|
||||
|
||||
let { children, data }: Props = $props();
|
||||
let { children }: Props = $props();
|
||||
|
||||
let clerk;
|
||||
|
||||
|
|
@ -45,52 +43,68 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
let message = $derived(messages.nav_greeting({ name: data.user.name }));
|
||||
</script>
|
||||
|
||||
{#snippet userMenu()}
|
||||
<div class="dropdown dropdown-end">
|
||||
<div tabindex="0" role="button" class="btn btn-circle btn-primary btn-sm ring">
|
||||
<div class="avatar placeholder online">
|
||||
<div class="w-8 rounded-full">
|
||||
{#if data.user.hasImage}
|
||||
<img src={data.user.imageUrl} alt="Avatar" />
|
||||
{:else}
|
||||
<span>{data.user.name.at(0)}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
tabindex={0}
|
||||
role="button"
|
||||
class="btn btn-primary btn-md flex items-center gap-2 text-lg"
|
||||
>
|
||||
<Menu />
|
||||
Menu
|
||||
</div>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="menu dropdown-content menu-lg z-[1] mt-4 w-52 rounded-box bg-base-200 p-2 text-right shadow"
|
||||
class="menu dropdown-content menu-lg z-[1] mt-4 w-52 rounded-box border border-neutral bg-base-200 p-2 text-right shadow"
|
||||
>
|
||||
<li>
|
||||
<button onclick={() => goto('/app/sms')}
|
||||
><MessageCircleMore /> {messages.nav_menu_sms()}</button
|
||||
>
|
||||
<button onclick={() => goto('/app/sms')}>
|
||||
<MessageCircleMore />
|
||||
{messages.nav_menu_sms()}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button onclick={() => goto('/app/residents')}>
|
||||
<UsersRound />
|
||||
{messages.nav_menu_residents()}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button onclick={() => goto('/app/settings')}>
|
||||
<Cog />
|
||||
{messages.nav_menu_settings()}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<SignOutButton>
|
||||
<LogOut />
|
||||
{messages.nav_menu_logout()}
|
||||
</SignOutButton>
|
||||
</li>
|
||||
<li><SignOutButton><LogOut /> {messages.nav_menu_logout()}</SignOutButton></li>
|
||||
</ul>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
<Navbar>
|
||||
{#snippet start()}
|
||||
<Button onclick={() => goto('/app')}>
|
||||
<h2 class="prose prose-xl">Hestia</h2>
|
||||
</Button>
|
||||
{/snippet}
|
||||
{#snippet center()}
|
||||
<h1 class="prose prose-2xl">Svelte</h1>
|
||||
{/snippet}
|
||||
{#snippet end()}
|
||||
<div class="flex items-center gap-3">
|
||||
<p class="prose prose-lg">{message}</p>
|
||||
{@render userMenu()}
|
||||
</div>
|
||||
{/snippet}
|
||||
</Navbar>
|
||||
{@render children()}
|
||||
<div class="flex h-full flex-col items-stretch gap-4">
|
||||
<Navbar>
|
||||
{#snippet start()}
|
||||
<Button onclick={() => goto('/app')} class="rounded-box" color="ghost">
|
||||
<h2 class="prose prose-xl">Hestia</h2>
|
||||
</Button>
|
||||
{/snippet}
|
||||
{#snippet center()}
|
||||
<h1 class="prose prose-2xl">Svelte</h1>
|
||||
{/snippet}
|
||||
{#snippet end()}
|
||||
<div class="flex items-center gap-4 pr-2">
|
||||
{@render userMenu()}
|
||||
</div>
|
||||
{/snippet}
|
||||
</Navbar>
|
||||
<div class="h-full rounded-box bg-base-200 p-8">
|
||||
{@render children()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { Avatar } from '$lib/components/Datadisplay';
|
||||
import { messages } from '$lib/i18n';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
type Props = {
|
||||
data: PageData;
|
||||
};
|
||||
|
||||
let { data }: Props = $props();
|
||||
|
||||
let message = $derived(messages.nav_greeting({ name: data.user.name }));
|
||||
let initials = $derived(data.user.name.split(' ').reduce((col, name) => col + name.at(0), ''));
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<Avatar img={data.user.imageUrl} placeholder={initials} size="sm" ring="primary" />
|
||||
<h1 class="prose prose-2xl">{message}</h1>
|
||||
</div>
|
||||
|
|
|
|||
90
src/routes/app/residents/+page.server.ts
Normal file
90
src/routes/app/residents/+page.server.ts
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import { PhoneRegex } from '$lib/regex/phone.js';
|
||||
import { logger } from '$lib/server/logger/index.js';
|
||||
import { prisma } from '$lib/server/prisma';
|
||||
import { fail } from '@sveltejs/kit';
|
||||
import zod from 'zod';
|
||||
|
||||
export const load = async ({ locals }) => {
|
||||
const residents = await prisma.resident.findMany({
|
||||
where: {
|
||||
tenantId: locals.tenant.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
phoneNumber: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
residents: residents,
|
||||
};
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
upsert: async (event) => {
|
||||
const form = await event.request.formData();
|
||||
|
||||
if (!form.has('name')) {
|
||||
return fail(400, { error: 'phone_missing' });
|
||||
}
|
||||
if (!form.get('phoneNumber')) {
|
||||
return fail(400, { error: 'message_missing' });
|
||||
}
|
||||
|
||||
const id = form.get('id');
|
||||
if (id && typeof id !== 'string') {
|
||||
return fail(400, { error: 'invalid_id' });
|
||||
}
|
||||
|
||||
const name = form.get('name');
|
||||
if (typeof name !== 'string') {
|
||||
return fail(400, { error: 'invalid_name' });
|
||||
}
|
||||
|
||||
const {
|
||||
success: phoneSuccess,
|
||||
data: phone,
|
||||
error: phoneError,
|
||||
} = zod.string().regex(PhoneRegex).safeParse(form.get('phoneNumber'));
|
||||
if (!phoneSuccess) {
|
||||
logger.error(phoneError);
|
||||
return fail(400, { error: 'invalid_phone' });
|
||||
}
|
||||
|
||||
await prisma.resident.upsert({
|
||||
where: {
|
||||
id: id ?? '',
|
||||
},
|
||||
create: {
|
||||
name: name,
|
||||
phoneNumber: phone,
|
||||
tenantId: event.locals.tenant.id,
|
||||
},
|
||||
update: {
|
||||
name: name,
|
||||
phoneNumber: phone,
|
||||
},
|
||||
});
|
||||
},
|
||||
delete: async (event) => {
|
||||
const form = await event.request.formData();
|
||||
|
||||
logger.info('Deleting Resident');
|
||||
|
||||
if (!form.has('id')) {
|
||||
return fail(400, { error: 'id_missing' });
|
||||
}
|
||||
|
||||
const id = form.get('id');
|
||||
if (typeof id !== 'string') {
|
||||
return fail(400, { error: 'invalid_id' });
|
||||
}
|
||||
|
||||
await prisma.resident.delete({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
98
src/routes/app/residents/+page.svelte
Normal file
98
src/routes/app/residents/+page.svelte
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { Button, Modal, ModalActions, ModalBody } from '$lib/components/Actions';
|
||||
import { TextInput } from '$lib/components/DataInput';
|
||||
import { ResidentTable, type ResidentItem } from '$lib/components/Residents';
|
||||
import { messages } from '$lib/i18n';
|
||||
import { Phone, UserRound, UserRoundPlus, X } from 'lucide-svelte';
|
||||
import type { ActionData, PageData } from './$types';
|
||||
|
||||
type Props = {
|
||||
data: PageData;
|
||||
form: ActionData;
|
||||
};
|
||||
|
||||
let { data }: Props = $props();
|
||||
|
||||
let residents = $derived(data.residents);
|
||||
|
||||
let dialog: HTMLDialogElement | undefined = $state(undefined);
|
||||
let form: HTMLFormElement | undefined = $state(undefined);
|
||||
|
||||
let resident: ResidentItem | undefined = $state(undefined);
|
||||
</script>
|
||||
|
||||
<Modal
|
||||
backdrop
|
||||
bind:dialog
|
||||
onclose={() => {
|
||||
resident = undefined;
|
||||
form?.reset();
|
||||
}}
|
||||
>
|
||||
<ModalBody>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl">
|
||||
{resident
|
||||
? messages.residents_modal_title_edit()
|
||||
: messages.residents_modal_title_new()}
|
||||
</h2>
|
||||
<form method="dialog">
|
||||
<Button color="ghost" shape="square" size="sm">
|
||||
<X />
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
<form method="POST" action="?/upsert" bind:this={form} use:enhance>
|
||||
{#if resident}
|
||||
<input type="hidden" name="id" value={resident.id} />
|
||||
{/if}
|
||||
<TextInput bordered name="name" value={resident?.name}>
|
||||
{#snippet label()}
|
||||
<UserRound size="18" />
|
||||
{messages.residents_modal_label_name()}
|
||||
{/snippet}
|
||||
</TextInput>
|
||||
<TextInput bordered name="phoneNumber" type={'tel'} value={resident?.phoneNumber}>
|
||||
{#snippet label()}
|
||||
<Phone size="18" />
|
||||
{messages.residents_modal_label_phone()}
|
||||
{/snippet}
|
||||
</TextInput>
|
||||
<ModalActions class="flex">
|
||||
<Button
|
||||
class="grow"
|
||||
type="submit"
|
||||
formaction="?/delete"
|
||||
color="error"
|
||||
onclick={() => dialog?.close()}
|
||||
>
|
||||
{messages.residents_modal_delete()}
|
||||
</Button>
|
||||
<Button class="grow" type="submit" color="primary" onclick={() => dialog?.close()}>
|
||||
{messages.residents_modal_submit()}
|
||||
</Button>
|
||||
</ModalActions>
|
||||
</form>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
|
||||
<div class="mx-auto flex max-w-5xl flex-col items-stretch gap-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<h1 class="text-4xl">{messages.residents_title()}</h1>
|
||||
<Button
|
||||
onclick={() => {
|
||||
dialog?.showModal();
|
||||
}}
|
||||
color="primary"><UserRoundPlus size="18" />{messages.residents_button_new()}</Button
|
||||
>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<ResidentTable
|
||||
items={residents}
|
||||
onEdit={(r) => {
|
||||
resident = r;
|
||||
dialog?.showModal();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
105
src/routes/app/settings/+page.server.ts
Normal file
105
src/routes/app/settings/+page.server.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { PhoneRegex } from '$lib/regex';
|
||||
import { logger } from '$lib/server/logger';
|
||||
import { prisma } from '$lib/server/prisma';
|
||||
import { encryptTwilioConfig, decryptTwilioConfig } from '$lib/server/twilio';
|
||||
import { fail, type Actions } from '@sveltejs/kit';
|
||||
import zod from 'zod';
|
||||
|
||||
export const load = async (event) => {
|
||||
const tenantId = event.locals.tenant.id;
|
||||
|
||||
const configs = await prisma.tenantConfig.findUnique({
|
||||
where: { tenantId: tenantId },
|
||||
select: {
|
||||
twilioConfig: {
|
||||
select: {
|
||||
accountSID: true,
|
||||
authToken: true,
|
||||
phoneNumber: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!configs) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
configs: {
|
||||
...(configs.twilioConfig && {
|
||||
twilioConfig: decryptTwilioConfig(configs.twilioConfig),
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
default: async (event) => {
|
||||
const form = await event.request.formData();
|
||||
const tenantId = event.locals.tenant.id;
|
||||
|
||||
if (!form.has('twilioAccountSID')) {
|
||||
return fail(400, { error: 'account_sid_missing' });
|
||||
}
|
||||
if (!form.has('twilioAuthToken')) {
|
||||
return fail(400, { error: 'auth_token_missing' });
|
||||
}
|
||||
if (!form.has('twilioPhoneNumber')) {
|
||||
return fail(400, { error: 'phone_number_missing' });
|
||||
}
|
||||
|
||||
const accountSID = form.get('twilioAccountSID');
|
||||
if (typeof accountSID !== 'string') {
|
||||
return fail(400, { error: 'invalid_account_sid' });
|
||||
}
|
||||
const authToken = form.get('twilioAuthToken');
|
||||
if (typeof authToken !== 'string') {
|
||||
return fail(400, { error: 'invalid_auth_token' });
|
||||
}
|
||||
const {
|
||||
success: phoneSuccess,
|
||||
data: phoneNumber,
|
||||
error: phoneError,
|
||||
} = zod.string().regex(PhoneRegex).safeParse(form.get('twilioPhoneNumber'));
|
||||
if (!phoneSuccess) {
|
||||
logger.error(phoneError);
|
||||
return fail(400, { error: 'invalid_phone_number' });
|
||||
}
|
||||
|
||||
const configs = await prisma.tenantConfig.upsert({
|
||||
where: {
|
||||
tenantId: tenantId,
|
||||
},
|
||||
create: {
|
||||
tenantId: tenantId,
|
||||
twilioConfig: {
|
||||
create: encryptTwilioConfig({
|
||||
accountSID: accountSID,
|
||||
authToken: authToken,
|
||||
phoneNumber: phoneNumber,
|
||||
}),
|
||||
},
|
||||
},
|
||||
update: {
|
||||
tenantId: tenantId,
|
||||
twilioConfig: {
|
||||
update: encryptTwilioConfig({
|
||||
accountSID: accountSID,
|
||||
authToken: authToken,
|
||||
phoneNumber: phoneNumber,
|
||||
}),
|
||||
},
|
||||
},
|
||||
select: { twilioConfig: true },
|
||||
});
|
||||
|
||||
return {
|
||||
configs: {
|
||||
...(configs.twilioConfig && {
|
||||
twilioConfig: decryptTwilioConfig(configs.twilioConfig),
|
||||
}),
|
||||
},
|
||||
};
|
||||
},
|
||||
} satisfies Actions;
|
||||
90
src/routes/app/settings/+page.svelte
Normal file
90
src/routes/app/settings/+page.svelte
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { Button } from '$lib/components/Actions';
|
||||
import { TextInput } from '$lib/components/DataInput';
|
||||
import Divider from '$lib/components/Layout/Divider.svelte';
|
||||
import { messages } from '$lib/i18n';
|
||||
import { Fingerprint, KeyRound, PhoneOutgoing } from 'lucide-svelte';
|
||||
import type { ActionData, PageData } from './$types';
|
||||
|
||||
type Props = {
|
||||
data: PageData;
|
||||
form: ActionData;
|
||||
};
|
||||
let { data, form }: Props = $props();
|
||||
|
||||
let configs = $derived(form?.configs ?? data.configs);
|
||||
</script>
|
||||
|
||||
<div class="page">
|
||||
<div class="card w-full max-w-xl bg-base-200 px-4 pt-4 shadow-xl">
|
||||
<div class="card-title justify-center">
|
||||
<h2 class="text-2xl font-semibold">{messages.settings_title()}</h2>
|
||||
{#if form?.error}
|
||||
<div role="alert" class="alert alert-error absolute -top-20">
|
||||
<i class="fi fi-bs-octagon-xmark h-6 w-6 shrink-0"></i>
|
||||
<span>{form.error}</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<form id="sms" method="POST" use:enhance>
|
||||
<div class="card-body">
|
||||
<Divider />
|
||||
<!-- Twilio -->
|
||||
<h2 class="text-2xl font-semibold">{messages.settings_category_twilio()}</h2>
|
||||
<TextInput
|
||||
defaultvalue={configs?.twilioConfig?.accountSID}
|
||||
name="twilioAccountSID"
|
||||
placeholder="..."
|
||||
bordered
|
||||
fade
|
||||
>
|
||||
{#snippet label()}
|
||||
<div class="flex gap-2">
|
||||
<Fingerprint size="18" />
|
||||
{messages.settings_twilio_account_sid()}
|
||||
</div>
|
||||
{/snippet}
|
||||
</TextInput>
|
||||
<TextInput
|
||||
defaultvalue={configs?.twilioConfig?.authToken}
|
||||
name="twilioAuthToken"
|
||||
placeholder="..."
|
||||
type="password"
|
||||
bordered
|
||||
fade
|
||||
>
|
||||
{#snippet label()}
|
||||
<div class="flex gap-2">
|
||||
<KeyRound size="18" />
|
||||
{messages.settings_twilio_auth_token()}
|
||||
</div>
|
||||
{/snippet}
|
||||
</TextInput>
|
||||
<TextInput
|
||||
defaultvalue={configs?.twilioConfig?.phoneNumber}
|
||||
name="twilioPhoneNumber"
|
||||
placeholder="+1XXX-XXX-XXXX"
|
||||
bordered
|
||||
fade
|
||||
>
|
||||
{#snippet label()}
|
||||
<div class="flex gap-2">
|
||||
<PhoneOutgoing size="18" />
|
||||
{messages.settings_twilio_phone_number()}
|
||||
</div>
|
||||
{/snippet}
|
||||
</TextInput>
|
||||
</div>
|
||||
<div class="card-actions justify-center px-8 pb-4">
|
||||
<Button type="submit" variant="outline" full>{messages.settings_save()}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
@apply flex flex-col items-center justify-around gap-24 py-[10%];
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,47 +1,110 @@
|
|||
import { TWILIO_PHONE_NUMBER } from '$env/static/private';
|
||||
import { PhoneRegex } from '$lib/regex';
|
||||
import type { Recipient } from '$lib/components/SMS';
|
||||
import { logger } from '$lib/server/logger';
|
||||
import { TwilioClient } from '$lib/server/twilio';
|
||||
import { prisma } from '$lib/server/prisma/index.js';
|
||||
import { decryptTwilioConfig } from '$lib/server/twilio/index.js';
|
||||
import { fail, type Actions } from '@sveltejs/kit';
|
||||
import twilio from 'twilio';
|
||||
import zod from 'zod';
|
||||
|
||||
export const load = async (event) => {
|
||||
const tenantId = event.locals.tenant.id;
|
||||
|
||||
const configs = await prisma.tenantConfig.findUnique({
|
||||
where: { tenantId: tenantId },
|
||||
select: {
|
||||
twilioConfig: {
|
||||
select: {
|
||||
accountSID: true,
|
||||
authToken: true,
|
||||
phoneNumber: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { success, error: validationError } = zod
|
||||
.object({
|
||||
accountSID: zod.string(),
|
||||
authToken: zod.string(),
|
||||
phoneNumber: zod.string(),
|
||||
})
|
||||
.safeParse(configs?.twilioConfig);
|
||||
|
||||
if (!success) {
|
||||
logger.warn(validationError.message);
|
||||
}
|
||||
|
||||
const residents = await prisma.resident.findMany({
|
||||
where: {
|
||||
tenantId: event.locals.tenant.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
phoneNumber: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
isTwilioConfigured: success,
|
||||
residents: residents,
|
||||
};
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
push: async (event) => {
|
||||
default: async (event) => {
|
||||
const form = await event.request.formData();
|
||||
|
||||
if (!form.has('phone')) {
|
||||
return fail(400, { error: 'phone_missing' });
|
||||
if (!form.has('recipients')) {
|
||||
return fail(400, { error: 'recipients_missing' });
|
||||
}
|
||||
if (!form.get('message')) {
|
||||
if (!form.has('message')) {
|
||||
return fail(400, { error: 'message_missing' });
|
||||
}
|
||||
|
||||
const {
|
||||
success: phoneSuccess,
|
||||
data: phone,
|
||||
error: phoneError,
|
||||
} = zod.string().regex(PhoneRegex).safeParse(form.get('phone'));
|
||||
if (!phoneSuccess) {
|
||||
logger.error(phoneError);
|
||||
return fail(400, { error: 'invalid_phone' });
|
||||
const recipients: Recipient[] = JSON.parse(form.get('recipients') as string);
|
||||
if (!Array.isArray(recipients)) {
|
||||
return fail(400, { error: 'invalid_recipients' });
|
||||
}
|
||||
logger.info(recipients);
|
||||
|
||||
const message = form.get('message');
|
||||
if (typeof message !== 'string') {
|
||||
return fail(400, { error: 'invalid_message' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await TwilioClient.messages.create({
|
||||
to: phone,
|
||||
body: message,
|
||||
from: TWILIO_PHONE_NUMBER,
|
||||
});
|
||||
logger.debug(result);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
fail(500, { success: false });
|
||||
const tenant = await prisma.tenantConfig.findUnique({
|
||||
where: {
|
||||
tenantId: event.locals.tenant.id,
|
||||
},
|
||||
select: {
|
||||
twilioConfig: true,
|
||||
},
|
||||
});
|
||||
|
||||
const config = tenant?.twilioConfig;
|
||||
if (!config) {
|
||||
return fail(307, { error: 'no_twilio_config' });
|
||||
}
|
||||
|
||||
const decryptedConfig = decryptTwilioConfig(config);
|
||||
|
||||
const client = twilio(decryptedConfig.accountSID, decryptedConfig.authToken);
|
||||
|
||||
for (const recipient of recipients) {
|
||||
try {
|
||||
const result = await client.messages.create({
|
||||
to: recipient.phone,
|
||||
body: message,
|
||||
from: decryptedConfig.phoneNumber,
|
||||
});
|
||||
logger.debug(result);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
fail(500, { success: false });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,68 +1,80 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Button } from '$lib/components/Actions';
|
||||
import { Textarea, TextInput } from '$lib/components/DataInput';
|
||||
import { fade } from 'svelte/transition';
|
||||
import type { ActionData } from './$types';
|
||||
import { Textarea } from '$lib/components/DataInput';
|
||||
import { Alert } from '$lib/components/Feedback';
|
||||
import { Link } from '$lib/components/Navigation';
|
||||
import { RecipientList, type Recipient } from '$lib/components/SMS';
|
||||
import { messages } from '$lib/i18n';
|
||||
import { CircleX, MessageCircleMore, TriangleAlert } from 'lucide-svelte';
|
||||
import type { ActionData, PageData } from './$types';
|
||||
|
||||
type Props = {
|
||||
data: PageData;
|
||||
form: ActionData;
|
||||
};
|
||||
let { form }: Props = $props();
|
||||
let { data, form }: Props = $props();
|
||||
|
||||
let recipients = $derived(
|
||||
data.residents.map((r) => ({ id: r.id, name: r.name, phone: r.phoneNumber }))
|
||||
);
|
||||
let selectedRecipients: Recipient[] = $state([]);
|
||||
</script>
|
||||
|
||||
{#snippet PhoneLabel()}
|
||||
<i class="fi fi-sr-phone-flip"></i> {messages.sms_label_phone()}
|
||||
{/snippet}
|
||||
|
||||
{#snippet MessageLabel()}
|
||||
<i class="fi fi-sr-comment-alt"></i> {messages.sms_label_message()}
|
||||
{/snippet}
|
||||
|
||||
{#snippet alert(message: string)}
|
||||
<div role="alert" class="alert alert-error absolute -top-20" transition:fade>
|
||||
<i class="fi fi-bs-octagon-xmark h-6 w-6 shrink-0"></i>
|
||||
<span>{message}</span>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
<div class="page" transition:fade>
|
||||
<div class="card bg-base-200 px-4 pt-4 shadow-xl">
|
||||
<div class="card-title justify-center">
|
||||
<h2 class="text-2xl font-semibold">{messages.sms_prompt()}</h2>
|
||||
{#if form?.error}
|
||||
{@render alert(form.error)}
|
||||
{/if}
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
{#if form?.error}
|
||||
<Alert class="flex w-fit justify-center" status="error">
|
||||
{#snippet icon()}
|
||||
<CircleX />
|
||||
{/snippet}
|
||||
<span>{form.error}</span>
|
||||
</Alert>
|
||||
{:else if !data.isTwilioConfigured}
|
||||
<Alert class="flex w-fit justify-center" status="warning">
|
||||
{#snippet icon()}
|
||||
<TriangleAlert />
|
||||
{/snippet}
|
||||
<span>
|
||||
Twilio must be configured on the <Link onclick={() => goto('/app/settings')}
|
||||
>Settings</Link
|
||||
> page
|
||||
</span>
|
||||
</Alert>
|
||||
{/if}
|
||||
<h2 class="text-4xl font-semibold">{messages.sms_prompt()}</h2>
|
||||
<div class="flex justify-center gap-4">
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<h2 class="text-3xl font-medium">Recipients</h2>
|
||||
<div class="h-full overflow-y-scroll rounded-lg bg-base-100 p-4">
|
||||
<RecipientList {recipients} bind:selected={selectedRecipients} />
|
||||
</div>
|
||||
</div>
|
||||
<form id="sms" method="POST" action="?/push" use:enhance>
|
||||
<div class="card-body">
|
||||
<TextInput
|
||||
type="tel"
|
||||
name="phone"
|
||||
label={PhoneLabel}
|
||||
placeholder="XXX-XXX-XXXX"
|
||||
bordered
|
||||
fade
|
||||
/>
|
||||
<form id="sms" method="POST" use:enhance>
|
||||
<div class="flex flex-col gap-4">
|
||||
<input name="recipients" type="hidden" value={JSON.stringify(selectedRecipients)} />
|
||||
<Textarea
|
||||
label={MessageLabel}
|
||||
disabled={!data.isTwilioConfigured}
|
||||
size="lg"
|
||||
error={form?.error}
|
||||
name="message"
|
||||
placeholder="..."
|
||||
form="sms"
|
||||
/>
|
||||
</div>
|
||||
<div class="card-actions justify-center px-8 pb-4">
|
||||
<Button type="submit" variant="outline" full>{messages.sms_button_submit()}</Button>
|
||||
resizable={false}
|
||||
cols={40}
|
||||
rows={12}
|
||||
>
|
||||
{#snippet label()}
|
||||
<span class="flex items-center gap-2 text-xl">
|
||||
<MessageCircleMore size="22" />
|
||||
{messages.sms_label_message()}
|
||||
</span>
|
||||
{/snippet}
|
||||
</Textarea>
|
||||
<Button full color="primary" disabled={!data.isTwilioConfigured} type="submit">
|
||||
{messages.sms_button_submit()}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
@apply flex flex-col items-center justify-around gap-24 py-[10%];
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import adapter from '@sveltejs/adapter-auto';
|
||||
import adapter from '@sveltejs/adapter-node';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue