diff --git a/.gitignore b/.gitignore
index 79518f7..65babd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,15 @@
node_modules
+
+/logs
# Output
.output
.vercel
/.svelte-kit
/build
+.idea
+
# OS
.DS_Store
Thumbs.db
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..5584653
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+# Build stage
+FROM node:18.18-alpine
+
+WORKDIR /app
+
+COPY . .
+
+RUN npm i -g pnpm
+
+EXPOSE 3000
+
+RUN chmod +x /app/docker_entrypoint.sh
+ENTRYPOINT ["/app/docker_entrypoint.sh"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 3df1afb..a959a8e 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,77 @@
-## Presentation
+
Projet Web - M1 ISA đź’»
-Creation of a project that use two or more NoSQL technologie: Redis & MangoDB
+
+ Technologies - Lancer le projet - Auteurs
+
-Front: JavaScript
+Projet réalisé dans le cadre du cours de Web languages for data storage and management .
-Back : Java (SpringBoot)
+đź’» Technologies
-Api to Server Mongo (Nabil's Server)
+- SvelteKit
+- MongoDB
+- Redis
+- Docker
-Update Redis Database
+🚀 Lancer le projet
+Afin de lancer le projet en local, vous aurez besoin de suivre les instructions suivantes
-
-
-# sv
-
-Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
-
-## Creating a project
-
-If you're seeing this, you've probably already done this step. Congrats!
+Clonez le dépôt
+Commencez par cloner le dépôt Git sur votre machine
```bash
-# create a new project in the current directory
-npx sv create
-
-# create a new project in my-app
-npx sv create my-app
+git clone https://github.com/NabilOuldHamou/M1_ProjetWeb
```
-## Developing
-
-Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+Production
+Installez **Docker** sur votre machine puis utilisez la commande suivante pour lancer le projet
```bash
-npm run dev
-
-# or start the server and open the app in a new browser tab
-npm run dev -- --open
+docker compose up
```
-## Building
+DĂ©veloppement
+TODO
-To create a production version of your app:
+🤝 Auteurs
-```bash
-npm run build
-```
+
diff --git a/components.json b/components.json
new file mode 100644
index 0000000..f95a168
--- /dev/null
+++ b/components.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "https://shadcn-svelte.com/schema.json",
+ "style": "default",
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "src/app.css",
+ "baseColor": "slate"
+ },
+ "aliases": {
+ "components": "$lib/components",
+ "utils": "$lib/utils"
+ },
+ "typescript": true
+}
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..b2ed544
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,59 @@
+services:
+
+ app:
+ build: .
+ hostname: app
+ depends_on:
+ - mongodb
+ - redis
+ environment:
+ - DATABASE_URL=mongodb://temp-root-username:temp-password@mongodb/chat_projetweb?authSource=admin
+ - JWT_SECRET=ba63466f102443f4bb6f3670891358bc4488d0c717f6ebcd3ee3c5144e55fe2d
+ ports:
+ - "3000:3000"
+ networks:
+ - app_network
+ volumes:
+ - .:/usr/src/app
+ - /usr/src/app/node_modules
+
+ mongodb:
+ build: ./mongodb_rs
+ hostname: mongodb
+ restart: always
+ environment:
+ - MONGO_INITDB_ROOT_USERNAME=temp-root-username
+ - MONGO_INITDB_ROOT_PASSWORD=temp-password
+ - MONGO_INITDB_DATABASE=chat_projetweb
+ - MONGO_REPLICA_HOST=mongodb
+ - MONGO_REPLICA_PORT=27017
+ ports:
+ - "27017:27017"
+ volumes:
+ - mongo-data:/data/db/
+ - mongo-logs:/var/log/mongodb/
+ networks:
+ - app_network
+
+ redis:
+ image: redis:latest
+ hostname: redis-server
+ restart: always
+ ports:
+ - "6379:6379"
+ command: redis-server --save 20 1 --loglevel warning
+ environment:
+ - REDIS_PASSWORD=temp-redis-password
+ volumes:
+ - redis-data:/root/redis
+ networks:
+ - app_network
+
+networks:
+ app_network:
+ driver: bridge
+
+volumes:
+ mongo-data:
+ mongo-logs:
+ redis-data:
\ No newline at end of file
diff --git a/docker_entrypoint.sh b/docker_entrypoint.sh
new file mode 100644
index 0000000..5d6f3b7
--- /dev/null
+++ b/docker_entrypoint.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+set -xe
+
+pnpm install
+pnpm prisma generate
+
+pnpm run build
+
+pnpx prisma db push
+
+ls
+
+node build
\ No newline at end of file
diff --git a/mongodb_rs/Dockerfile b/mongodb_rs/Dockerfile
new file mode 100644
index 0000000..9bbc3d1
--- /dev/null
+++ b/mongodb_rs/Dockerfile
@@ -0,0 +1,11 @@
+FROM mongo:5
+
+# we take over the default & start mongo in replica set mode in a background task
+ENTRYPOINT mongod --port $MONGO_REPLICA_PORT --replSet rs0 --bind_ip 0.0.0.0 & MONGOD_PID=$!; \
+# we prepare the replica set with a single node and prepare the root user config
+INIT_REPL_CMD="rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: '$MONGO_REPLICA_HOST:$MONGO_REPLICA_PORT' }] })"; \
+INIT_USER_CMD="db.getUser('$MONGO_INITDB_ROOT_USERNAME') || db.createUser({ user: '$MONGO_INITDB_ROOT_USERNAME', pwd: '$MONGO_INITDB_ROOT_PASSWORD', roles: ['root'] })"; \
+# we wait for the replica set to be ready and then submit the command just above
+until (mongo admin --port $MONGO_REPLICA_PORT --eval "$INIT_REPL_CMD && $INIT_USER_CMD"); do sleep 1; done; \
+# we are done but we keep the container by waiting on signals from the mongo task
+echo "REPLICA SET ONLINE"; wait $MONGOD_PID;
\ No newline at end of file
diff --git a/package.json b/package.json
index 36a8fdf..3363bdc 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,8 @@
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"autoprefixer": "^10.4.20",
+ "bits-ui": "^0.21.16",
+ "clsx": "^2.1.1",
"eslint": "^9.7.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0",
@@ -26,9 +28,27 @@
"prettier-plugin-tailwindcss": "^0.6.5",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
+ "tailwind-merge": "^2.5.5",
+ "tailwind-variants": "^0.3.0",
"tailwindcss": "^3.4.9",
"typescript": "^5.0.0",
- "typescript-eslint": "^8.0.0",
- "vite": "^5.0.3"
+ "typescript-eslint": "^8.0.0"
+ },
+ "dependencies": {
+ "@prisma/client": "^5.22.0",
+ "@sveltejs/adapter-node": "^5.2.10",
+ "@types/jsonwebtoken": "^9.0.7",
+ "@types/node": "^22.10.1",
+ "argon2": "^0.41.1",
+ "jsonwebtoken": "^9.0.2",
+ "lucide-svelte": "^0.462.0",
+ "multer": "^1.4.5-lts.1",
+ "prisma": "^5.22.0",
+ "redis": "^4.7.0",
+ "socket.io": "^4.8.1",
+ "socket.io-client": "^4.8.1",
+ "svelte-radix": "^2.0.1",
+ "vite": "^5.0.3",
+ "winston": "^3.17.0"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
deleted file mode 100644
index 11d7b17..0000000
--- a/pnpm-lock.yaml
+++ /dev/null
@@ -1,2750 +0,0 @@
-lockfileVersion: '9.0'
-
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
-importers:
-
- .:
- devDependencies:
- '@sveltejs/adapter-auto':
- specifier: ^3.0.0
- version: 3.3.1(@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11))
- '@sveltejs/kit':
- specifier: ^2.0.0
- version: 2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)
- '@sveltejs/vite-plugin-svelte':
- specifier: ^4.0.0
- version: 4.0.2(svelte@5.2.7)(vite@5.4.11)
- autoprefixer:
- specifier: ^10.4.20
- version: 10.4.20(postcss@8.4.49)
- eslint:
- specifier: ^9.7.0
- version: 9.15.0(jiti@1.21.6)
- eslint-config-prettier:
- specifier: ^9.1.0
- version: 9.1.0(eslint@9.15.0(jiti@1.21.6))
- eslint-plugin-svelte:
- specifier: ^2.36.0
- version: 2.46.0(eslint@9.15.0(jiti@1.21.6))(svelte@5.2.7)
- globals:
- specifier: ^15.0.0
- version: 15.12.0
- mdsvex:
- specifier: ^0.11.2
- version: 0.11.2(svelte@5.2.7)
- prettier:
- specifier: ^3.3.2
- version: 3.3.3
- prettier-plugin-svelte:
- specifier: ^3.2.6
- version: 3.3.2(prettier@3.3.3)(svelte@5.2.7)
- prettier-plugin-tailwindcss:
- specifier: ^0.6.5
- version: 0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.3.3)(svelte@5.2.7))(prettier@3.3.3)
- svelte:
- specifier: ^5.0.0
- version: 5.2.7
- svelte-check:
- specifier: ^4.0.0
- version: 4.1.0(svelte@5.2.7)(typescript@5.7.2)
- tailwindcss:
- specifier: ^3.4.9
- version: 3.4.15
- typescript:
- specifier: ^5.0.0
- version: 5.7.2
- typescript-eslint:
- specifier: ^8.0.0
- version: 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- vite:
- specifier: ^5.0.3
- version: 5.4.11
-
-packages:
-
- '@alloc/quick-lru@5.2.0':
- resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
- engines: {node: '>=10'}
-
- '@ampproject/remapping@2.3.0':
- resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
- engines: {node: '>=6.0.0'}
-
- '@esbuild/aix-ppc64@0.21.5':
- resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [aix]
-
- '@esbuild/android-arm64@0.21.5':
- resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [android]
-
- '@esbuild/android-arm@0.21.5':
- resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [android]
-
- '@esbuild/android-x64@0.21.5':
- resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [android]
-
- '@esbuild/darwin-arm64@0.21.5':
- resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [darwin]
-
- '@esbuild/darwin-x64@0.21.5':
- resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [darwin]
-
- '@esbuild/freebsd-arm64@0.21.5':
- resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [freebsd]
-
- '@esbuild/freebsd-x64@0.21.5':
- resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [freebsd]
-
- '@esbuild/linux-arm64@0.21.5':
- resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [linux]
-
- '@esbuild/linux-arm@0.21.5':
- resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [linux]
-
- '@esbuild/linux-ia32@0.21.5':
- resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [linux]
-
- '@esbuild/linux-loong64@0.21.5':
- resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
- engines: {node: '>=12'}
- cpu: [loong64]
- os: [linux]
-
- '@esbuild/linux-mips64el@0.21.5':
- resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
- engines: {node: '>=12'}
- cpu: [mips64el]
- os: [linux]
-
- '@esbuild/linux-ppc64@0.21.5':
- resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [linux]
-
- '@esbuild/linux-riscv64@0.21.5':
- resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
- engines: {node: '>=12'}
- cpu: [riscv64]
- os: [linux]
-
- '@esbuild/linux-s390x@0.21.5':
- resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
- engines: {node: '>=12'}
- cpu: [s390x]
- os: [linux]
-
- '@esbuild/linux-x64@0.21.5':
- resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [linux]
-
- '@esbuild/netbsd-x64@0.21.5':
- resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [netbsd]
-
- '@esbuild/openbsd-x64@0.21.5':
- resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [openbsd]
-
- '@esbuild/sunos-x64@0.21.5':
- resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [sunos]
-
- '@esbuild/win32-arm64@0.21.5':
- resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [win32]
-
- '@esbuild/win32-ia32@0.21.5':
- resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [win32]
-
- '@esbuild/win32-x64@0.21.5':
- resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [win32]
-
- '@eslint-community/eslint-utils@4.4.1':
- resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
-
- '@eslint-community/regexpp@4.12.1':
- resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
- engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
-
- '@eslint/config-array@0.19.0':
- resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/core@0.9.0':
- resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/eslintrc@3.2.0':
- resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/js@9.15.0':
- resolution: {integrity: sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/object-schema@2.1.4':
- resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/plugin-kit@0.2.3':
- resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@humanfs/core@0.19.1':
- resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
- engines: {node: '>=18.18.0'}
-
- '@humanfs/node@0.16.6':
- resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==}
- engines: {node: '>=18.18.0'}
-
- '@humanwhocodes/module-importer@1.0.1':
- resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
- engines: {node: '>=12.22'}
-
- '@humanwhocodes/retry@0.3.1':
- resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
- engines: {node: '>=18.18'}
-
- '@humanwhocodes/retry@0.4.1':
- resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==}
- engines: {node: '>=18.18'}
-
- '@isaacs/cliui@8.0.2':
- resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
- engines: {node: '>=12'}
-
- '@jridgewell/gen-mapping@0.3.5':
- resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/resolve-uri@3.1.2':
- resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/set-array@1.2.1':
- resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
- engines: {node: '>=6.0.0'}
-
- '@jridgewell/sourcemap-codec@1.5.0':
- resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
-
- '@jridgewell/trace-mapping@0.3.25':
- resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
-
- '@nodelib/fs.scandir@2.1.5':
- resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.stat@2.0.5':
- resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
- engines: {node: '>= 8'}
-
- '@nodelib/fs.walk@1.2.8':
- resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
- engines: {node: '>= 8'}
-
- '@pkgjs/parseargs@0.11.0':
- resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
- engines: {node: '>=14'}
-
- '@polka/url@1.0.0-next.28':
- resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
-
- '@rollup/rollup-android-arm-eabi@4.27.4':
- resolution: {integrity: sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==}
- cpu: [arm]
- os: [android]
-
- '@rollup/rollup-android-arm64@4.27.4':
- resolution: {integrity: sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==}
- cpu: [arm64]
- os: [android]
-
- '@rollup/rollup-darwin-arm64@4.27.4':
- resolution: {integrity: sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==}
- cpu: [arm64]
- os: [darwin]
-
- '@rollup/rollup-darwin-x64@4.27.4':
- resolution: {integrity: sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==}
- cpu: [x64]
- os: [darwin]
-
- '@rollup/rollup-freebsd-arm64@4.27.4':
- resolution: {integrity: sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==}
- cpu: [arm64]
- os: [freebsd]
-
- '@rollup/rollup-freebsd-x64@4.27.4':
- resolution: {integrity: sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==}
- cpu: [x64]
- os: [freebsd]
-
- '@rollup/rollup-linux-arm-gnueabihf@4.27.4':
- resolution: {integrity: sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==}
- cpu: [arm]
- os: [linux]
-
- '@rollup/rollup-linux-arm-musleabihf@4.27.4':
- resolution: {integrity: sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==}
- cpu: [arm]
- os: [linux]
-
- '@rollup/rollup-linux-arm64-gnu@4.27.4':
- resolution: {integrity: sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==}
- cpu: [arm64]
- os: [linux]
-
- '@rollup/rollup-linux-arm64-musl@4.27.4':
- resolution: {integrity: sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==}
- cpu: [arm64]
- os: [linux]
-
- '@rollup/rollup-linux-powerpc64le-gnu@4.27.4':
- resolution: {integrity: sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==}
- cpu: [ppc64]
- os: [linux]
-
- '@rollup/rollup-linux-riscv64-gnu@4.27.4':
- resolution: {integrity: sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==}
- cpu: [riscv64]
- os: [linux]
-
- '@rollup/rollup-linux-s390x-gnu@4.27.4':
- resolution: {integrity: sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==}
- cpu: [s390x]
- os: [linux]
-
- '@rollup/rollup-linux-x64-gnu@4.27.4':
- resolution: {integrity: sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==}
- cpu: [x64]
- os: [linux]
-
- '@rollup/rollup-linux-x64-musl@4.27.4':
- resolution: {integrity: sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==}
- cpu: [x64]
- os: [linux]
-
- '@rollup/rollup-win32-arm64-msvc@4.27.4':
- resolution: {integrity: sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==}
- cpu: [arm64]
- os: [win32]
-
- '@rollup/rollup-win32-ia32-msvc@4.27.4':
- resolution: {integrity: sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==}
- cpu: [ia32]
- os: [win32]
-
- '@rollup/rollup-win32-x64-msvc@4.27.4':
- resolution: {integrity: sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==}
- cpu: [x64]
- os: [win32]
-
- '@sveltejs/adapter-auto@3.3.1':
- resolution: {integrity: sha512-5Sc7WAxYdL6q9j/+D0jJKjGREGlfIevDyHSQ2eNETHcB1TKlQWHcAo8AS8H1QdjNvSXpvOwNjykDUHPEAyGgdQ==}
- peerDependencies:
- '@sveltejs/kit': ^2.0.0
-
- '@sveltejs/kit@2.8.3':
- resolution: {integrity: sha512-DVBVwugfzzn0SxKA+eAmKqcZ7aHZROCHxH7/pyrOi+HLtQ721eEsctGb9MkhEuqj6q/9S/OFYdn37vdxzFPdvw==}
- engines: {node: '>=18.13'}
- hasBin: true
- peerDependencies:
- '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1
- svelte: ^4.0.0 || ^5.0.0-next.0
- vite: ^5.0.3
-
- '@sveltejs/vite-plugin-svelte-inspector@3.0.1':
- resolution: {integrity: sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==}
- engines: {node: ^18.0.0 || ^20.0.0 || >=22}
- peerDependencies:
- '@sveltejs/vite-plugin-svelte': ^4.0.0-next.0||^4.0.0
- svelte: ^5.0.0-next.96 || ^5.0.0
- vite: ^5.0.0
-
- '@sveltejs/vite-plugin-svelte@4.0.2':
- resolution: {integrity: sha512-Y9r/fWy539XlAC7+5wfNJ4zH6TygUYoQ0Eegzp0zDDqhJ54+92gOyOX1l4MO1cJSx0O+Gp13YePT5XEa3+kX0w==}
- engines: {node: ^18.0.0 || ^20.0.0 || >=22}
- peerDependencies:
- svelte: ^5.0.0-next.96 || ^5.0.0
- vite: ^5.0.0
-
- '@types/cookie@0.6.0':
- resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
-
- '@types/estree@1.0.6':
- resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
-
- '@types/json-schema@7.0.15':
- resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
-
- '@types/unist@2.0.11':
- resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
-
- '@typescript-eslint/eslint-plugin@8.15.0':
- resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- '@typescript-eslint/parser@8.15.0':
- resolution: {integrity: sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- '@typescript-eslint/scope-manager@8.15.0':
- resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/type-utils@8.15.0':
- resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- '@typescript-eslint/types@8.15.0':
- resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/typescript-estree@8.15.0':
- resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- '@typescript-eslint/utils@8.15.0':
- resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- '@typescript-eslint/visitor-keys@8.15.0':
- resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- acorn-jsx@5.3.2:
- resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
- peerDependencies:
- acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
-
- acorn-typescript@1.4.13:
- resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==}
- peerDependencies:
- acorn: '>=8.9.0'
-
- acorn@8.14.0:
- resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
- engines: {node: '>=0.4.0'}
- hasBin: true
-
- ajv@6.12.6:
- resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
-
- ansi-regex@5.0.1:
- resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
- engines: {node: '>=8'}
-
- ansi-regex@6.1.0:
- resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
- engines: {node: '>=12'}
-
- ansi-styles@4.3.0:
- resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
- engines: {node: '>=8'}
-
- ansi-styles@6.2.1:
- resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
- engines: {node: '>=12'}
-
- any-promise@1.3.0:
- resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
-
- anymatch@3.1.3:
- resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
- engines: {node: '>= 8'}
-
- arg@5.0.2:
- resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
-
- argparse@2.0.1:
- resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
-
- aria-query@5.3.2:
- resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
- engines: {node: '>= 0.4'}
-
- autoprefixer@10.4.20:
- resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
- engines: {node: ^10 || ^12 || >=14}
- hasBin: true
- peerDependencies:
- postcss: ^8.1.0
-
- axobject-query@4.1.0:
- resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
- engines: {node: '>= 0.4'}
-
- balanced-match@1.0.2:
- resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
-
- binary-extensions@2.3.0:
- resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
- engines: {node: '>=8'}
-
- brace-expansion@1.1.11:
- resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
-
- brace-expansion@2.0.1:
- resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
-
- braces@3.0.3:
- resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
- engines: {node: '>=8'}
-
- browserslist@4.24.2:
- resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==}
- engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
- hasBin: true
-
- callsites@3.1.0:
- resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
- engines: {node: '>=6'}
-
- camelcase-css@2.0.1:
- resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
- engines: {node: '>= 6'}
-
- caniuse-lite@1.0.30001684:
- resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==}
-
- chalk@4.1.2:
- resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
- engines: {node: '>=10'}
-
- chokidar@3.6.0:
- resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
- engines: {node: '>= 8.10.0'}
-
- chokidar@4.0.1:
- resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==}
- engines: {node: '>= 14.16.0'}
-
- color-convert@2.0.1:
- resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
- engines: {node: '>=7.0.0'}
-
- color-name@1.1.4:
- resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
-
- commander@4.1.1:
- resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
- engines: {node: '>= 6'}
-
- concat-map@0.0.1:
- resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
-
- cookie@0.6.0:
- resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
- engines: {node: '>= 0.6'}
-
- cross-spawn@7.0.6:
- resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
- engines: {node: '>= 8'}
-
- cssesc@3.0.0:
- resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
- engines: {node: '>=4'}
- hasBin: true
-
- debug@4.3.7:
- resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
- engines: {node: '>=6.0'}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
-
- deep-is@0.1.4:
- resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
-
- deepmerge@4.3.1:
- resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
- engines: {node: '>=0.10.0'}
-
- devalue@5.1.1:
- resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
-
- didyoumean@1.2.2:
- resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
-
- dlv@1.1.3:
- resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
-
- eastasianwidth@0.2.0:
- resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
-
- electron-to-chromium@1.5.64:
- resolution: {integrity: sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==}
-
- emoji-regex@8.0.0:
- resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
-
- emoji-regex@9.2.2:
- resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
-
- esbuild@0.21.5:
- resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
- engines: {node: '>=12'}
- hasBin: true
-
- escalade@3.2.0:
- resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
- engines: {node: '>=6'}
-
- escape-string-regexp@4.0.0:
- resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
- engines: {node: '>=10'}
-
- eslint-compat-utils@0.5.1:
- resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==}
- engines: {node: '>=12'}
- peerDependencies:
- eslint: '>=6.0.0'
-
- eslint-config-prettier@9.1.0:
- resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
- hasBin: true
- peerDependencies:
- eslint: '>=7.0.0'
-
- eslint-plugin-svelte@2.46.0:
- resolution: {integrity: sha512-1A7iEMkzmCZ9/Iz+EAfOGYL8IoIG6zeKEq1SmpxGeM5SXmoQq+ZNnCpXFVJpsxPWYx8jIVGMerQMzX20cqUl0g==}
- engines: {node: ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0
- svelte: ^3.37.0 || ^4.0.0 || ^5.0.0
- peerDependenciesMeta:
- svelte:
- optional: true
-
- eslint-scope@7.2.2:
- resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- eslint-scope@8.2.0:
- resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint-visitor-keys@3.4.3:
- resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- eslint-visitor-keys@4.2.0:
- resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint@9.15.0:
- resolution: {integrity: sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- hasBin: true
- peerDependencies:
- jiti: '*'
- peerDependenciesMeta:
- jiti:
- optional: true
-
- esm-env@1.1.4:
- resolution: {integrity: sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg==}
-
- espree@10.3.0:
- resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- espree@9.6.1:
- resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- esquery@1.6.0:
- resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
- engines: {node: '>=0.10'}
-
- esrap@1.2.2:
- resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==}
-
- esrecurse@4.3.0:
- resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
- engines: {node: '>=4.0'}
-
- estraverse@5.3.0:
- resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
- engines: {node: '>=4.0'}
-
- esutils@2.0.3:
- resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
- engines: {node: '>=0.10.0'}
-
- fast-deep-equal@3.1.3:
- resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
-
- fast-glob@3.3.2:
- resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
- engines: {node: '>=8.6.0'}
-
- fast-json-stable-stringify@2.1.0:
- resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
-
- fast-levenshtein@2.0.6:
- resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
-
- fastq@1.17.1:
- resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
-
- fdir@6.4.2:
- resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==}
- peerDependencies:
- picomatch: ^3 || ^4
- peerDependenciesMeta:
- picomatch:
- optional: true
-
- file-entry-cache@8.0.0:
- resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
- engines: {node: '>=16.0.0'}
-
- fill-range@7.1.1:
- resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
- engines: {node: '>=8'}
-
- find-up@5.0.0:
- resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
- engines: {node: '>=10'}
-
- flat-cache@4.0.1:
- resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
- engines: {node: '>=16'}
-
- flatted@3.3.2:
- resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
-
- foreground-child@3.3.0:
- resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
- engines: {node: '>=14'}
-
- fraction.js@4.3.7:
- resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
-
- fsevents@2.3.3:
- resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
- engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
- os: [darwin]
-
- function-bind@1.1.2:
- resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
-
- glob-parent@5.1.2:
- resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
- engines: {node: '>= 6'}
-
- glob-parent@6.0.2:
- resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
- engines: {node: '>=10.13.0'}
-
- glob@10.4.5:
- resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
- hasBin: true
-
- globals@14.0.0:
- resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
- engines: {node: '>=18'}
-
- globals@15.12.0:
- resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==}
- engines: {node: '>=18'}
-
- globalyzer@0.1.0:
- resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==}
-
- globrex@0.1.2:
- resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
-
- graphemer@1.4.0:
- resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
-
- has-flag@4.0.0:
- resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
- engines: {node: '>=8'}
-
- hasown@2.0.2:
- resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
- engines: {node: '>= 0.4'}
-
- ignore@5.3.2:
- resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
- engines: {node: '>= 4'}
-
- import-fresh@3.3.0:
- resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
- engines: {node: '>=6'}
-
- import-meta-resolve@4.1.0:
- resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==}
-
- imurmurhash@0.1.4:
- resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
- engines: {node: '>=0.8.19'}
-
- is-binary-path@2.1.0:
- resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
- engines: {node: '>=8'}
-
- is-core-module@2.15.1:
- resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
- engines: {node: '>= 0.4'}
-
- is-extglob@2.1.1:
- resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
- engines: {node: '>=0.10.0'}
-
- is-fullwidth-code-point@3.0.0:
- resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
- engines: {node: '>=8'}
-
- is-glob@4.0.3:
- resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
- engines: {node: '>=0.10.0'}
-
- is-number@7.0.0:
- resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
- engines: {node: '>=0.12.0'}
-
- is-reference@3.0.3:
- resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
-
- isexe@2.0.0:
- resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
-
- jackspeak@3.4.3:
- resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
-
- jiti@1.21.6:
- resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
- hasBin: true
-
- js-yaml@4.1.0:
- resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
- hasBin: true
-
- json-buffer@3.0.1:
- resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
-
- json-schema-traverse@0.4.1:
- resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
-
- json-stable-stringify-without-jsonify@1.0.1:
- resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
-
- keyv@4.5.4:
- resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
-
- kleur@4.1.5:
- resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
- engines: {node: '>=6'}
-
- known-css-properties@0.35.0:
- resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==}
-
- levn@0.4.1:
- resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
- engines: {node: '>= 0.8.0'}
-
- lilconfig@2.1.0:
- resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
- engines: {node: '>=10'}
-
- lilconfig@3.1.2:
- resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==}
- engines: {node: '>=14'}
-
- lines-and-columns@1.2.4:
- resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
-
- locate-character@3.0.0:
- resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
-
- locate-path@6.0.0:
- resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
- engines: {node: '>=10'}
-
- lodash.merge@4.6.2:
- resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
-
- lru-cache@10.4.3:
- resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
-
- magic-string@0.30.13:
- resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==}
-
- mdsvex@0.11.2:
- resolution: {integrity: sha512-Y4ab+vLvTJS88196Scb/RFNaHMHVSWw6CwfsgWIQP8f42D57iDII0/qABSu530V4pkv8s6T2nx3ds0MC1VwFLA==}
- peerDependencies:
- svelte: ^3.56.0 || ^4.0.0 || ^5.0.0-next.120
-
- merge2@1.4.1:
- resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
- engines: {node: '>= 8'}
-
- micromatch@4.0.8:
- resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
- engines: {node: '>=8.6'}
-
- minimatch@3.1.2:
- resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
-
- minimatch@9.0.5:
- resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- minipass@7.1.2:
- resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
- engines: {node: '>=16 || 14 >=14.17'}
-
- mri@1.2.0:
- resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
- engines: {node: '>=4'}
-
- mrmime@2.0.0:
- resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
- engines: {node: '>=10'}
-
- ms@2.1.3:
- resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
-
- mz@2.7.0:
- resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
-
- nanoid@3.3.7:
- resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
- engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
- hasBin: true
-
- natural-compare@1.4.0:
- resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
-
- node-releases@2.0.18:
- resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
-
- normalize-path@3.0.0:
- resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
- engines: {node: '>=0.10.0'}
-
- normalize-range@0.1.2:
- resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
- engines: {node: '>=0.10.0'}
-
- object-assign@4.1.1:
- resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
- engines: {node: '>=0.10.0'}
-
- object-hash@3.0.0:
- resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
- engines: {node: '>= 6'}
-
- optionator@0.9.4:
- resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
- engines: {node: '>= 0.8.0'}
-
- p-limit@3.1.0:
- resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
- engines: {node: '>=10'}
-
- p-locate@5.0.0:
- resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
- engines: {node: '>=10'}
-
- package-json-from-dist@1.0.1:
- resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
-
- parent-module@1.0.1:
- resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
- engines: {node: '>=6'}
-
- path-exists@4.0.0:
- resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
- engines: {node: '>=8'}
-
- path-key@3.1.1:
- resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
- engines: {node: '>=8'}
-
- path-parse@1.0.7:
- resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
-
- path-scurry@1.11.1:
- resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
- engines: {node: '>=16 || 14 >=14.18'}
-
- picocolors@1.1.1:
- resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
-
- picomatch@2.3.1:
- resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
- engines: {node: '>=8.6'}
-
- pify@2.3.0:
- resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
- engines: {node: '>=0.10.0'}
-
- pirates@4.0.6:
- resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
- engines: {node: '>= 6'}
-
- postcss-import@15.1.0:
- resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
- engines: {node: '>=14.0.0'}
- peerDependencies:
- postcss: ^8.0.0
-
- postcss-js@4.0.1:
- resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
- engines: {node: ^12 || ^14 || >= 16}
- peerDependencies:
- postcss: ^8.4.21
-
- postcss-load-config@3.1.4:
- resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
- engines: {node: '>= 10'}
- peerDependencies:
- postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
- peerDependenciesMeta:
- postcss:
- optional: true
- ts-node:
- optional: true
-
- postcss-load-config@4.0.2:
- resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
- engines: {node: '>= 14'}
- peerDependencies:
- postcss: '>=8.0.9'
- ts-node: '>=9.0.0'
- peerDependenciesMeta:
- postcss:
- optional: true
- ts-node:
- optional: true
-
- postcss-nested@6.2.0:
- resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
- engines: {node: '>=12.0'}
- peerDependencies:
- postcss: ^8.2.14
-
- postcss-safe-parser@6.0.0:
- resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==}
- engines: {node: '>=12.0'}
- peerDependencies:
- postcss: ^8.3.3
-
- postcss-scss@4.0.9:
- resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==}
- engines: {node: '>=12.0'}
- peerDependencies:
- postcss: ^8.4.29
-
- postcss-selector-parser@6.1.2:
- resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
- engines: {node: '>=4'}
-
- postcss-value-parser@4.2.0:
- resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
-
- postcss@8.4.49:
- resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
- engines: {node: ^10 || ^12 || >=14}
-
- prelude-ls@1.2.1:
- resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
- engines: {node: '>= 0.8.0'}
-
- prettier-plugin-svelte@3.3.2:
- resolution: {integrity: sha512-kRPjH8wSj2iu+dO+XaUv4vD8qr5mdDmlak3IT/7AOgGIMRG86z/EHOLauFcClKEnOUf4A4nOA7sre5KrJD4Raw==}
- peerDependencies:
- prettier: ^3.0.0
- svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0
-
- prettier-plugin-tailwindcss@0.6.9:
- resolution: {integrity: sha512-r0i3uhaZAXYP0At5xGfJH876W3HHGHDp+LCRUJrs57PBeQ6mYHMwr25KH8NPX44F2yGTvdnH7OqCshlQx183Eg==}
- engines: {node: '>=14.21.3'}
- peerDependencies:
- '@ianvs/prettier-plugin-sort-imports': '*'
- '@prettier/plugin-pug': '*'
- '@shopify/prettier-plugin-liquid': '*'
- '@trivago/prettier-plugin-sort-imports': '*'
- '@zackad/prettier-plugin-twig-melody': '*'
- prettier: ^3.0
- prettier-plugin-astro: '*'
- prettier-plugin-css-order: '*'
- prettier-plugin-import-sort: '*'
- prettier-plugin-jsdoc: '*'
- prettier-plugin-marko: '*'
- prettier-plugin-multiline-arrays: '*'
- prettier-plugin-organize-attributes: '*'
- prettier-plugin-organize-imports: '*'
- prettier-plugin-sort-imports: '*'
- prettier-plugin-style-order: '*'
- prettier-plugin-svelte: '*'
- peerDependenciesMeta:
- '@ianvs/prettier-plugin-sort-imports':
- optional: true
- '@prettier/plugin-pug':
- optional: true
- '@shopify/prettier-plugin-liquid':
- optional: true
- '@trivago/prettier-plugin-sort-imports':
- optional: true
- '@zackad/prettier-plugin-twig-melody':
- optional: true
- prettier-plugin-astro:
- optional: true
- prettier-plugin-css-order:
- optional: true
- prettier-plugin-import-sort:
- optional: true
- prettier-plugin-jsdoc:
- optional: true
- prettier-plugin-marko:
- optional: true
- prettier-plugin-multiline-arrays:
- optional: true
- prettier-plugin-organize-attributes:
- optional: true
- prettier-plugin-organize-imports:
- optional: true
- prettier-plugin-sort-imports:
- optional: true
- prettier-plugin-style-order:
- optional: true
- prettier-plugin-svelte:
- optional: true
-
- prettier@3.3.3:
- resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
- engines: {node: '>=14'}
- hasBin: true
-
- prism-svelte@0.4.7:
- resolution: {integrity: sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ==}
-
- prismjs@1.29.0:
- resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
- engines: {node: '>=6'}
-
- punycode@2.3.1:
- resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
- engines: {node: '>=6'}
-
- queue-microtask@1.2.3:
- resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
-
- read-cache@1.0.0:
- resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
-
- readdirp@3.6.0:
- resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
- engines: {node: '>=8.10.0'}
-
- readdirp@4.0.2:
- resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
- engines: {node: '>= 14.16.0'}
-
- resolve-from@4.0.0:
- resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
- engines: {node: '>=4'}
-
- resolve@1.22.8:
- resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
- hasBin: true
-
- reusify@1.0.4:
- resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
- engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
-
- rollup@4.27.4:
- resolution: {integrity: sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==}
- engines: {node: '>=18.0.0', npm: '>=8.0.0'}
- hasBin: true
-
- run-parallel@1.2.0:
- resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
-
- sade@1.8.1:
- resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
- engines: {node: '>=6'}
-
- semver@7.6.3:
- resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
- engines: {node: '>=10'}
- hasBin: true
-
- set-cookie-parser@2.7.1:
- resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
-
- shebang-command@2.0.0:
- resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
- engines: {node: '>=8'}
-
- shebang-regex@3.0.0:
- resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
- engines: {node: '>=8'}
-
- signal-exit@4.1.0:
- resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
- engines: {node: '>=14'}
-
- sirv@3.0.0:
- resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
- engines: {node: '>=18'}
-
- source-map-js@1.2.1:
- resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
- engines: {node: '>=0.10.0'}
-
- string-width@4.2.3:
- resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
- engines: {node: '>=8'}
-
- string-width@5.1.2:
- resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
- engines: {node: '>=12'}
-
- strip-ansi@6.0.1:
- resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
- engines: {node: '>=8'}
-
- strip-ansi@7.1.0:
- resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
- engines: {node: '>=12'}
-
- strip-json-comments@3.1.1:
- resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
- engines: {node: '>=8'}
-
- sucrase@3.35.0:
- resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
- engines: {node: '>=16 || 14 >=14.17'}
- hasBin: true
-
- supports-color@7.2.0:
- resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
- engines: {node: '>=8'}
-
- supports-preserve-symlinks-flag@1.0.0:
- resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
- engines: {node: '>= 0.4'}
-
- svelte-check@4.1.0:
- resolution: {integrity: sha512-AflEZYqI578KuDZcpcorPSf597LStxlkN7XqXi38u09zlHODVKd7c+7OuubGzbhgGRUqNTdQCZ+Ga96iRXEf2g==}
- engines: {node: '>= 18.0.0'}
- hasBin: true
- peerDependencies:
- svelte: ^4.0.0 || ^5.0.0-next.0
- typescript: '>=5.0.0'
-
- svelte-eslint-parser@0.43.0:
- resolution: {integrity: sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- svelte: ^3.37.0 || ^4.0.0 || ^5.0.0
- peerDependenciesMeta:
- svelte:
- optional: true
-
- svelte@5.2.7:
- resolution: {integrity: sha512-cEhPGuLHiH2+Z8B1FwQgiZJgA39uUmJR4516TKrM5zrp0/cuwJkfhUfcTxhAkznanAF5fXUKzvYR4o+Ksx3ZCQ==}
- engines: {node: '>=18'}
-
- tailwindcss@3.4.15:
- resolution: {integrity: sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==}
- engines: {node: '>=14.0.0'}
- hasBin: true
-
- thenify-all@1.6.0:
- resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
- engines: {node: '>=0.8'}
-
- thenify@3.3.1:
- resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
-
- tiny-glob@0.2.9:
- resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==}
-
- to-regex-range@5.0.1:
- resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
- engines: {node: '>=8.0'}
-
- totalist@3.0.1:
- resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
- engines: {node: '>=6'}
-
- ts-api-utils@1.4.1:
- resolution: {integrity: sha512-5RU2/lxTA3YUZxju61HO2U6EoZLvBLtmV2mbTvqyu4a/7s7RmJPT+1YekhMVsQhznRWk/czIwDUg+V8Q9ZuG4w==}
- engines: {node: '>=16'}
- peerDependencies:
- typescript: '>=4.2.0'
-
- ts-interface-checker@0.1.13:
- resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
-
- type-check@0.4.0:
- resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
- engines: {node: '>= 0.8.0'}
-
- typescript-eslint@8.15.0:
- resolution: {integrity: sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
-
- typescript@5.7.2:
- resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==}
- engines: {node: '>=14.17'}
- hasBin: true
-
- unist-util-stringify-position@2.0.3:
- resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==}
-
- update-browserslist-db@1.1.1:
- resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
- hasBin: true
- peerDependencies:
- browserslist: '>= 4.21.0'
-
- uri-js@4.4.1:
- resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
-
- util-deprecate@1.0.2:
- resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
-
- vfile-message@2.0.4:
- resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==}
-
- vite@5.4.11:
- resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
- engines: {node: ^18.0.0 || >=20.0.0}
- hasBin: true
- peerDependencies:
- '@types/node': ^18.0.0 || >=20.0.0
- less: '*'
- lightningcss: ^1.21.0
- sass: '*'
- sass-embedded: '*'
- stylus: '*'
- sugarss: '*'
- terser: ^5.4.0
- peerDependenciesMeta:
- '@types/node':
- optional: true
- less:
- optional: true
- lightningcss:
- optional: true
- sass:
- optional: true
- sass-embedded:
- optional: true
- stylus:
- optional: true
- sugarss:
- optional: true
- terser:
- optional: true
-
- vitefu@1.0.3:
- resolution: {integrity: sha512-iKKfOMBHob2WxEJbqbJjHAkmYgvFDPhuqrO82om83S8RLk+17FtyMBfcyeH8GqD0ihShtkMW/zzJgiA51hCNCQ==}
- peerDependencies:
- vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0
- peerDependenciesMeta:
- vite:
- optional: true
-
- which@2.0.2:
- resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
- engines: {node: '>= 8'}
- hasBin: true
-
- word-wrap@1.2.5:
- resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
- engines: {node: '>=0.10.0'}
-
- wrap-ansi@7.0.0:
- resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
- engines: {node: '>=10'}
-
- wrap-ansi@8.1.0:
- resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
- engines: {node: '>=12'}
-
- yaml@1.10.2:
- resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
- engines: {node: '>= 6'}
-
- yaml@2.6.1:
- resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==}
- engines: {node: '>= 14'}
- hasBin: true
-
- yocto-queue@0.1.0:
- resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
- engines: {node: '>=10'}
-
- zimmerframe@1.1.2:
- resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
-
-snapshots:
-
- '@alloc/quick-lru@5.2.0': {}
-
- '@ampproject/remapping@2.3.0':
- dependencies:
- '@jridgewell/gen-mapping': 0.3.5
- '@jridgewell/trace-mapping': 0.3.25
-
- '@esbuild/aix-ppc64@0.21.5':
- optional: true
-
- '@esbuild/android-arm64@0.21.5':
- optional: true
-
- '@esbuild/android-arm@0.21.5':
- optional: true
-
- '@esbuild/android-x64@0.21.5':
- optional: true
-
- '@esbuild/darwin-arm64@0.21.5':
- optional: true
-
- '@esbuild/darwin-x64@0.21.5':
- optional: true
-
- '@esbuild/freebsd-arm64@0.21.5':
- optional: true
-
- '@esbuild/freebsd-x64@0.21.5':
- optional: true
-
- '@esbuild/linux-arm64@0.21.5':
- optional: true
-
- '@esbuild/linux-arm@0.21.5':
- optional: true
-
- '@esbuild/linux-ia32@0.21.5':
- optional: true
-
- '@esbuild/linux-loong64@0.21.5':
- optional: true
-
- '@esbuild/linux-mips64el@0.21.5':
- optional: true
-
- '@esbuild/linux-ppc64@0.21.5':
- optional: true
-
- '@esbuild/linux-riscv64@0.21.5':
- optional: true
-
- '@esbuild/linux-s390x@0.21.5':
- optional: true
-
- '@esbuild/linux-x64@0.21.5':
- optional: true
-
- '@esbuild/netbsd-x64@0.21.5':
- optional: true
-
- '@esbuild/openbsd-x64@0.21.5':
- optional: true
-
- '@esbuild/sunos-x64@0.21.5':
- optional: true
-
- '@esbuild/win32-arm64@0.21.5':
- optional: true
-
- '@esbuild/win32-ia32@0.21.5':
- optional: true
-
- '@esbuild/win32-x64@0.21.5':
- optional: true
-
- '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0(jiti@1.21.6))':
- dependencies:
- eslint: 9.15.0(jiti@1.21.6)
- eslint-visitor-keys: 3.4.3
-
- '@eslint-community/regexpp@4.12.1': {}
-
- '@eslint/config-array@0.19.0':
- dependencies:
- '@eslint/object-schema': 2.1.4
- debug: 4.3.7
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/core@0.9.0': {}
-
- '@eslint/eslintrc@3.2.0':
- dependencies:
- ajv: 6.12.6
- debug: 4.3.7
- espree: 10.3.0
- globals: 14.0.0
- ignore: 5.3.2
- import-fresh: 3.3.0
- js-yaml: 4.1.0
- minimatch: 3.1.2
- strip-json-comments: 3.1.1
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/js@9.15.0': {}
-
- '@eslint/object-schema@2.1.4': {}
-
- '@eslint/plugin-kit@0.2.3':
- dependencies:
- levn: 0.4.1
-
- '@humanfs/core@0.19.1': {}
-
- '@humanfs/node@0.16.6':
- dependencies:
- '@humanfs/core': 0.19.1
- '@humanwhocodes/retry': 0.3.1
-
- '@humanwhocodes/module-importer@1.0.1': {}
-
- '@humanwhocodes/retry@0.3.1': {}
-
- '@humanwhocodes/retry@0.4.1': {}
-
- '@isaacs/cliui@8.0.2':
- dependencies:
- string-width: 5.1.2
- string-width-cjs: string-width@4.2.3
- strip-ansi: 7.1.0
- strip-ansi-cjs: strip-ansi@6.0.1
- wrap-ansi: 8.1.0
- wrap-ansi-cjs: wrap-ansi@7.0.0
-
- '@jridgewell/gen-mapping@0.3.5':
- dependencies:
- '@jridgewell/set-array': 1.2.1
- '@jridgewell/sourcemap-codec': 1.5.0
- '@jridgewell/trace-mapping': 0.3.25
-
- '@jridgewell/resolve-uri@3.1.2': {}
-
- '@jridgewell/set-array@1.2.1': {}
-
- '@jridgewell/sourcemap-codec@1.5.0': {}
-
- '@jridgewell/trace-mapping@0.3.25':
- dependencies:
- '@jridgewell/resolve-uri': 3.1.2
- '@jridgewell/sourcemap-codec': 1.5.0
-
- '@nodelib/fs.scandir@2.1.5':
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- run-parallel: 1.2.0
-
- '@nodelib/fs.stat@2.0.5': {}
-
- '@nodelib/fs.walk@1.2.8':
- dependencies:
- '@nodelib/fs.scandir': 2.1.5
- fastq: 1.17.1
-
- '@pkgjs/parseargs@0.11.0':
- optional: true
-
- '@polka/url@1.0.0-next.28': {}
-
- '@rollup/rollup-android-arm-eabi@4.27.4':
- optional: true
-
- '@rollup/rollup-android-arm64@4.27.4':
- optional: true
-
- '@rollup/rollup-darwin-arm64@4.27.4':
- optional: true
-
- '@rollup/rollup-darwin-x64@4.27.4':
- optional: true
-
- '@rollup/rollup-freebsd-arm64@4.27.4':
- optional: true
-
- '@rollup/rollup-freebsd-x64@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-arm-gnueabihf@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-arm-musleabihf@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-arm64-gnu@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-arm64-musl@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-powerpc64le-gnu@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-riscv64-gnu@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-s390x-gnu@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-x64-gnu@4.27.4':
- optional: true
-
- '@rollup/rollup-linux-x64-musl@4.27.4':
- optional: true
-
- '@rollup/rollup-win32-arm64-msvc@4.27.4':
- optional: true
-
- '@rollup/rollup-win32-ia32-msvc@4.27.4':
- optional: true
-
- '@rollup/rollup-win32-x64-msvc@4.27.4':
- optional: true
-
- '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11))':
- dependencies:
- '@sveltejs/kit': 2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)
- import-meta-resolve: 4.1.0
-
- '@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)':
- dependencies:
- '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@5.2.7)(vite@5.4.11)
- '@types/cookie': 0.6.0
- cookie: 0.6.0
- devalue: 5.1.1
- esm-env: 1.1.4
- import-meta-resolve: 4.1.0
- kleur: 4.1.5
- magic-string: 0.30.13
- mrmime: 2.0.0
- sade: 1.8.1
- set-cookie-parser: 2.7.1
- sirv: 3.0.0
- svelte: 5.2.7
- tiny-glob: 0.2.9
- vite: 5.4.11
-
- '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)':
- dependencies:
- '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@5.2.7)(vite@5.4.11)
- debug: 4.3.7
- svelte: 5.2.7
- vite: 5.4.11
- transitivePeerDependencies:
- - supports-color
-
- '@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11)':
- dependencies:
- '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)
- debug: 4.3.7
- deepmerge: 4.3.1
- kleur: 4.1.5
- magic-string: 0.30.13
- svelte: 5.2.7
- vite: 5.4.11
- vitefu: 1.0.3(vite@5.4.11)
- transitivePeerDependencies:
- - supports-color
-
- '@types/cookie@0.6.0': {}
-
- '@types/estree@1.0.6': {}
-
- '@types/json-schema@7.0.15': {}
-
- '@types/unist@2.0.11': {}
-
- '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)':
- dependencies:
- '@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- '@typescript-eslint/scope-manager': 8.15.0
- '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- '@typescript-eslint/visitor-keys': 8.15.0
- eslint: 9.15.0(jiti@1.21.6)
- graphemer: 1.4.0
- ignore: 5.3.2
- natural-compare: 1.4.0
- ts-api-utils: 1.4.1(typescript@5.7.2)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)':
- dependencies:
- '@typescript-eslint/scope-manager': 8.15.0
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2)
- '@typescript-eslint/visitor-keys': 8.15.0
- debug: 4.3.7
- eslint: 9.15.0(jiti@1.21.6)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/scope-manager@8.15.0':
- dependencies:
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/visitor-keys': 8.15.0
-
- '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)':
- dependencies:
- '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- debug: 4.3.7
- eslint: 9.15.0(jiti@1.21.6)
- ts-api-utils: 1.4.1(typescript@5.7.2)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/types@8.15.0': {}
-
- '@typescript-eslint/typescript-estree@8.15.0(typescript@5.7.2)':
- dependencies:
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/visitor-keys': 8.15.0
- debug: 4.3.7
- fast-glob: 3.3.2
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.6.3
- ts-api-utils: 1.4.1(typescript@5.7.2)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/utils@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)':
- dependencies:
- '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@1.21.6))
- '@typescript-eslint/scope-manager': 8.15.0
- '@typescript-eslint/types': 8.15.0
- '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.7.2)
- eslint: 9.15.0(jiti@1.21.6)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
- '@typescript-eslint/visitor-keys@8.15.0':
- dependencies:
- '@typescript-eslint/types': 8.15.0
- eslint-visitor-keys: 4.2.0
-
- acorn-jsx@5.3.2(acorn@8.14.0):
- dependencies:
- acorn: 8.14.0
-
- acorn-typescript@1.4.13(acorn@8.14.0):
- dependencies:
- acorn: 8.14.0
-
- acorn@8.14.0: {}
-
- ajv@6.12.6:
- dependencies:
- fast-deep-equal: 3.1.3
- fast-json-stable-stringify: 2.1.0
- json-schema-traverse: 0.4.1
- uri-js: 4.4.1
-
- ansi-regex@5.0.1: {}
-
- ansi-regex@6.1.0: {}
-
- ansi-styles@4.3.0:
- dependencies:
- color-convert: 2.0.1
-
- ansi-styles@6.2.1: {}
-
- any-promise@1.3.0: {}
-
- anymatch@3.1.3:
- dependencies:
- normalize-path: 3.0.0
- picomatch: 2.3.1
-
- arg@5.0.2: {}
-
- argparse@2.0.1: {}
-
- aria-query@5.3.2: {}
-
- autoprefixer@10.4.20(postcss@8.4.49):
- dependencies:
- browserslist: 4.24.2
- caniuse-lite: 1.0.30001684
- fraction.js: 4.3.7
- normalize-range: 0.1.2
- picocolors: 1.1.1
- postcss: 8.4.49
- postcss-value-parser: 4.2.0
-
- axobject-query@4.1.0: {}
-
- balanced-match@1.0.2: {}
-
- binary-extensions@2.3.0: {}
-
- brace-expansion@1.1.11:
- dependencies:
- balanced-match: 1.0.2
- concat-map: 0.0.1
-
- brace-expansion@2.0.1:
- dependencies:
- balanced-match: 1.0.2
-
- braces@3.0.3:
- dependencies:
- fill-range: 7.1.1
-
- browserslist@4.24.2:
- dependencies:
- caniuse-lite: 1.0.30001684
- electron-to-chromium: 1.5.64
- node-releases: 2.0.18
- update-browserslist-db: 1.1.1(browserslist@4.24.2)
-
- callsites@3.1.0: {}
-
- camelcase-css@2.0.1: {}
-
- caniuse-lite@1.0.30001684: {}
-
- chalk@4.1.2:
- dependencies:
- ansi-styles: 4.3.0
- supports-color: 7.2.0
-
- chokidar@3.6.0:
- dependencies:
- anymatch: 3.1.3
- braces: 3.0.3
- glob-parent: 5.1.2
- is-binary-path: 2.1.0
- is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.6.0
- optionalDependencies:
- fsevents: 2.3.3
-
- chokidar@4.0.1:
- dependencies:
- readdirp: 4.0.2
-
- color-convert@2.0.1:
- dependencies:
- color-name: 1.1.4
-
- color-name@1.1.4: {}
-
- commander@4.1.1: {}
-
- concat-map@0.0.1: {}
-
- cookie@0.6.0: {}
-
- cross-spawn@7.0.6:
- dependencies:
- path-key: 3.1.1
- shebang-command: 2.0.0
- which: 2.0.2
-
- cssesc@3.0.0: {}
-
- debug@4.3.7:
- dependencies:
- ms: 2.1.3
-
- deep-is@0.1.4: {}
-
- deepmerge@4.3.1: {}
-
- devalue@5.1.1: {}
-
- didyoumean@1.2.2: {}
-
- dlv@1.1.3: {}
-
- eastasianwidth@0.2.0: {}
-
- electron-to-chromium@1.5.64: {}
-
- emoji-regex@8.0.0: {}
-
- emoji-regex@9.2.2: {}
-
- esbuild@0.21.5:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.21.5
- '@esbuild/android-arm': 0.21.5
- '@esbuild/android-arm64': 0.21.5
- '@esbuild/android-x64': 0.21.5
- '@esbuild/darwin-arm64': 0.21.5
- '@esbuild/darwin-x64': 0.21.5
- '@esbuild/freebsd-arm64': 0.21.5
- '@esbuild/freebsd-x64': 0.21.5
- '@esbuild/linux-arm': 0.21.5
- '@esbuild/linux-arm64': 0.21.5
- '@esbuild/linux-ia32': 0.21.5
- '@esbuild/linux-loong64': 0.21.5
- '@esbuild/linux-mips64el': 0.21.5
- '@esbuild/linux-ppc64': 0.21.5
- '@esbuild/linux-riscv64': 0.21.5
- '@esbuild/linux-s390x': 0.21.5
- '@esbuild/linux-x64': 0.21.5
- '@esbuild/netbsd-x64': 0.21.5
- '@esbuild/openbsd-x64': 0.21.5
- '@esbuild/sunos-x64': 0.21.5
- '@esbuild/win32-arm64': 0.21.5
- '@esbuild/win32-ia32': 0.21.5
- '@esbuild/win32-x64': 0.21.5
-
- escalade@3.2.0: {}
-
- escape-string-regexp@4.0.0: {}
-
- eslint-compat-utils@0.5.1(eslint@9.15.0(jiti@1.21.6)):
- dependencies:
- eslint: 9.15.0(jiti@1.21.6)
- semver: 7.6.3
-
- eslint-config-prettier@9.1.0(eslint@9.15.0(jiti@1.21.6)):
- dependencies:
- eslint: 9.15.0(jiti@1.21.6)
-
- eslint-plugin-svelte@2.46.0(eslint@9.15.0(jiti@1.21.6))(svelte@5.2.7):
- dependencies:
- '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@1.21.6))
- '@jridgewell/sourcemap-codec': 1.5.0
- eslint: 9.15.0(jiti@1.21.6)
- eslint-compat-utils: 0.5.1(eslint@9.15.0(jiti@1.21.6))
- esutils: 2.0.3
- known-css-properties: 0.35.0
- postcss: 8.4.49
- postcss-load-config: 3.1.4(postcss@8.4.49)
- postcss-safe-parser: 6.0.0(postcss@8.4.49)
- postcss-selector-parser: 6.1.2
- semver: 7.6.3
- svelte-eslint-parser: 0.43.0(svelte@5.2.7)
- optionalDependencies:
- svelte: 5.2.7
- transitivePeerDependencies:
- - ts-node
-
- eslint-scope@7.2.2:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
- eslint-scope@8.2.0:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
- eslint-visitor-keys@3.4.3: {}
-
- eslint-visitor-keys@4.2.0: {}
-
- eslint@9.15.0(jiti@1.21.6):
- dependencies:
- '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0(jiti@1.21.6))
- '@eslint-community/regexpp': 4.12.1
- '@eslint/config-array': 0.19.0
- '@eslint/core': 0.9.0
- '@eslint/eslintrc': 3.2.0
- '@eslint/js': 9.15.0
- '@eslint/plugin-kit': 0.2.3
- '@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.6
- chalk: 4.1.2
- cross-spawn: 7.0.6
- debug: 4.3.7
- escape-string-regexp: 4.0.0
- eslint-scope: 8.2.0
- eslint-visitor-keys: 4.2.0
- espree: 10.3.0
- esquery: 1.6.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 8.0.0
- find-up: 5.0.0
- glob-parent: 6.0.2
- ignore: 5.3.2
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- json-stable-stringify-without-jsonify: 1.0.1
- lodash.merge: 4.6.2
- minimatch: 3.1.2
- natural-compare: 1.4.0
- optionator: 0.9.4
- optionalDependencies:
- jiti: 1.21.6
- transitivePeerDependencies:
- - supports-color
-
- esm-env@1.1.4: {}
-
- espree@10.3.0:
- dependencies:
- acorn: 8.14.0
- acorn-jsx: 5.3.2(acorn@8.14.0)
- eslint-visitor-keys: 4.2.0
-
- espree@9.6.1:
- dependencies:
- acorn: 8.14.0
- acorn-jsx: 5.3.2(acorn@8.14.0)
- eslint-visitor-keys: 3.4.3
-
- esquery@1.6.0:
- dependencies:
- estraverse: 5.3.0
-
- esrap@1.2.2:
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.0
- '@types/estree': 1.0.6
-
- esrecurse@4.3.0:
- dependencies:
- estraverse: 5.3.0
-
- estraverse@5.3.0: {}
-
- esutils@2.0.3: {}
-
- fast-deep-equal@3.1.3: {}
-
- fast-glob@3.3.2:
- dependencies:
- '@nodelib/fs.stat': 2.0.5
- '@nodelib/fs.walk': 1.2.8
- glob-parent: 5.1.2
- merge2: 1.4.1
- micromatch: 4.0.8
-
- fast-json-stable-stringify@2.1.0: {}
-
- fast-levenshtein@2.0.6: {}
-
- fastq@1.17.1:
- dependencies:
- reusify: 1.0.4
-
- fdir@6.4.2: {}
-
- file-entry-cache@8.0.0:
- dependencies:
- flat-cache: 4.0.1
-
- fill-range@7.1.1:
- dependencies:
- to-regex-range: 5.0.1
-
- find-up@5.0.0:
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
-
- flat-cache@4.0.1:
- dependencies:
- flatted: 3.3.2
- keyv: 4.5.4
-
- flatted@3.3.2: {}
-
- foreground-child@3.3.0:
- dependencies:
- cross-spawn: 7.0.6
- signal-exit: 4.1.0
-
- fraction.js@4.3.7: {}
-
- fsevents@2.3.3:
- optional: true
-
- function-bind@1.1.2: {}
-
- glob-parent@5.1.2:
- dependencies:
- is-glob: 4.0.3
-
- glob-parent@6.0.2:
- dependencies:
- is-glob: 4.0.3
-
- glob@10.4.5:
- dependencies:
- foreground-child: 3.3.0
- jackspeak: 3.4.3
- minimatch: 9.0.5
- minipass: 7.1.2
- package-json-from-dist: 1.0.1
- path-scurry: 1.11.1
-
- globals@14.0.0: {}
-
- globals@15.12.0: {}
-
- globalyzer@0.1.0: {}
-
- globrex@0.1.2: {}
-
- graphemer@1.4.0: {}
-
- has-flag@4.0.0: {}
-
- hasown@2.0.2:
- dependencies:
- function-bind: 1.1.2
-
- ignore@5.3.2: {}
-
- import-fresh@3.3.0:
- dependencies:
- parent-module: 1.0.1
- resolve-from: 4.0.0
-
- import-meta-resolve@4.1.0: {}
-
- imurmurhash@0.1.4: {}
-
- is-binary-path@2.1.0:
- dependencies:
- binary-extensions: 2.3.0
-
- is-core-module@2.15.1:
- dependencies:
- hasown: 2.0.2
-
- is-extglob@2.1.1: {}
-
- is-fullwidth-code-point@3.0.0: {}
-
- is-glob@4.0.3:
- dependencies:
- is-extglob: 2.1.1
-
- is-number@7.0.0: {}
-
- is-reference@3.0.3:
- dependencies:
- '@types/estree': 1.0.6
-
- isexe@2.0.0: {}
-
- jackspeak@3.4.3:
- dependencies:
- '@isaacs/cliui': 8.0.2
- optionalDependencies:
- '@pkgjs/parseargs': 0.11.0
-
- jiti@1.21.6: {}
-
- js-yaml@4.1.0:
- dependencies:
- argparse: 2.0.1
-
- json-buffer@3.0.1: {}
-
- json-schema-traverse@0.4.1: {}
-
- json-stable-stringify-without-jsonify@1.0.1: {}
-
- keyv@4.5.4:
- dependencies:
- json-buffer: 3.0.1
-
- kleur@4.1.5: {}
-
- known-css-properties@0.35.0: {}
-
- levn@0.4.1:
- dependencies:
- prelude-ls: 1.2.1
- type-check: 0.4.0
-
- lilconfig@2.1.0: {}
-
- lilconfig@3.1.2: {}
-
- lines-and-columns@1.2.4: {}
-
- locate-character@3.0.0: {}
-
- locate-path@6.0.0:
- dependencies:
- p-locate: 5.0.0
-
- lodash.merge@4.6.2: {}
-
- lru-cache@10.4.3: {}
-
- magic-string@0.30.13:
- dependencies:
- '@jridgewell/sourcemap-codec': 1.5.0
-
- mdsvex@0.11.2(svelte@5.2.7):
- dependencies:
- '@types/unist': 2.0.11
- prism-svelte: 0.4.7
- prismjs: 1.29.0
- svelte: 5.2.7
- vfile-message: 2.0.4
-
- merge2@1.4.1: {}
-
- micromatch@4.0.8:
- dependencies:
- braces: 3.0.3
- picomatch: 2.3.1
-
- minimatch@3.1.2:
- dependencies:
- brace-expansion: 1.1.11
-
- minimatch@9.0.5:
- dependencies:
- brace-expansion: 2.0.1
-
- minipass@7.1.2: {}
-
- mri@1.2.0: {}
-
- mrmime@2.0.0: {}
-
- ms@2.1.3: {}
-
- mz@2.7.0:
- dependencies:
- any-promise: 1.3.0
- object-assign: 4.1.1
- thenify-all: 1.6.0
-
- nanoid@3.3.7: {}
-
- natural-compare@1.4.0: {}
-
- node-releases@2.0.18: {}
-
- normalize-path@3.0.0: {}
-
- normalize-range@0.1.2: {}
-
- object-assign@4.1.1: {}
-
- object-hash@3.0.0: {}
-
- optionator@0.9.4:
- dependencies:
- deep-is: 0.1.4
- fast-levenshtein: 2.0.6
- levn: 0.4.1
- prelude-ls: 1.2.1
- type-check: 0.4.0
- word-wrap: 1.2.5
-
- p-limit@3.1.0:
- dependencies:
- yocto-queue: 0.1.0
-
- p-locate@5.0.0:
- dependencies:
- p-limit: 3.1.0
-
- package-json-from-dist@1.0.1: {}
-
- parent-module@1.0.1:
- dependencies:
- callsites: 3.1.0
-
- path-exists@4.0.0: {}
-
- path-key@3.1.1: {}
-
- path-parse@1.0.7: {}
-
- path-scurry@1.11.1:
- dependencies:
- lru-cache: 10.4.3
- minipass: 7.1.2
-
- picocolors@1.1.1: {}
-
- picomatch@2.3.1: {}
-
- pify@2.3.0: {}
-
- pirates@4.0.6: {}
-
- postcss-import@15.1.0(postcss@8.4.49):
- dependencies:
- postcss: 8.4.49
- postcss-value-parser: 4.2.0
- read-cache: 1.0.0
- resolve: 1.22.8
-
- postcss-js@4.0.1(postcss@8.4.49):
- dependencies:
- camelcase-css: 2.0.1
- postcss: 8.4.49
-
- postcss-load-config@3.1.4(postcss@8.4.49):
- dependencies:
- lilconfig: 2.1.0
- yaml: 1.10.2
- optionalDependencies:
- postcss: 8.4.49
-
- postcss-load-config@4.0.2(postcss@8.4.49):
- dependencies:
- lilconfig: 3.1.2
- yaml: 2.6.1
- optionalDependencies:
- postcss: 8.4.49
-
- postcss-nested@6.2.0(postcss@8.4.49):
- dependencies:
- postcss: 8.4.49
- postcss-selector-parser: 6.1.2
-
- postcss-safe-parser@6.0.0(postcss@8.4.49):
- dependencies:
- postcss: 8.4.49
-
- postcss-scss@4.0.9(postcss@8.4.49):
- dependencies:
- postcss: 8.4.49
-
- postcss-selector-parser@6.1.2:
- dependencies:
- cssesc: 3.0.0
- util-deprecate: 1.0.2
-
- postcss-value-parser@4.2.0: {}
-
- postcss@8.4.49:
- dependencies:
- nanoid: 3.3.7
- picocolors: 1.1.1
- source-map-js: 1.2.1
-
- prelude-ls@1.2.1: {}
-
- prettier-plugin-svelte@3.3.2(prettier@3.3.3)(svelte@5.2.7):
- dependencies:
- prettier: 3.3.3
- svelte: 5.2.7
-
- prettier-plugin-tailwindcss@0.6.9(prettier-plugin-svelte@3.3.2(prettier@3.3.3)(svelte@5.2.7))(prettier@3.3.3):
- dependencies:
- prettier: 3.3.3
- optionalDependencies:
- prettier-plugin-svelte: 3.3.2(prettier@3.3.3)(svelte@5.2.7)
-
- prettier@3.3.3: {}
-
- prism-svelte@0.4.7: {}
-
- prismjs@1.29.0: {}
-
- punycode@2.3.1: {}
-
- queue-microtask@1.2.3: {}
-
- read-cache@1.0.0:
- dependencies:
- pify: 2.3.0
-
- readdirp@3.6.0:
- dependencies:
- picomatch: 2.3.1
-
- readdirp@4.0.2: {}
-
- resolve-from@4.0.0: {}
-
- resolve@1.22.8:
- dependencies:
- is-core-module: 2.15.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
- reusify@1.0.4: {}
-
- rollup@4.27.4:
- dependencies:
- '@types/estree': 1.0.6
- optionalDependencies:
- '@rollup/rollup-android-arm-eabi': 4.27.4
- '@rollup/rollup-android-arm64': 4.27.4
- '@rollup/rollup-darwin-arm64': 4.27.4
- '@rollup/rollup-darwin-x64': 4.27.4
- '@rollup/rollup-freebsd-arm64': 4.27.4
- '@rollup/rollup-freebsd-x64': 4.27.4
- '@rollup/rollup-linux-arm-gnueabihf': 4.27.4
- '@rollup/rollup-linux-arm-musleabihf': 4.27.4
- '@rollup/rollup-linux-arm64-gnu': 4.27.4
- '@rollup/rollup-linux-arm64-musl': 4.27.4
- '@rollup/rollup-linux-powerpc64le-gnu': 4.27.4
- '@rollup/rollup-linux-riscv64-gnu': 4.27.4
- '@rollup/rollup-linux-s390x-gnu': 4.27.4
- '@rollup/rollup-linux-x64-gnu': 4.27.4
- '@rollup/rollup-linux-x64-musl': 4.27.4
- '@rollup/rollup-win32-arm64-msvc': 4.27.4
- '@rollup/rollup-win32-ia32-msvc': 4.27.4
- '@rollup/rollup-win32-x64-msvc': 4.27.4
- fsevents: 2.3.3
-
- run-parallel@1.2.0:
- dependencies:
- queue-microtask: 1.2.3
-
- sade@1.8.1:
- dependencies:
- mri: 1.2.0
-
- semver@7.6.3: {}
-
- set-cookie-parser@2.7.1: {}
-
- shebang-command@2.0.0:
- dependencies:
- shebang-regex: 3.0.0
-
- shebang-regex@3.0.0: {}
-
- signal-exit@4.1.0: {}
-
- sirv@3.0.0:
- dependencies:
- '@polka/url': 1.0.0-next.28
- mrmime: 2.0.0
- totalist: 3.0.1
-
- source-map-js@1.2.1: {}
-
- string-width@4.2.3:
- dependencies:
- emoji-regex: 8.0.0
- is-fullwidth-code-point: 3.0.0
- strip-ansi: 6.0.1
-
- string-width@5.1.2:
- dependencies:
- eastasianwidth: 0.2.0
- emoji-regex: 9.2.2
- strip-ansi: 7.1.0
-
- strip-ansi@6.0.1:
- dependencies:
- ansi-regex: 5.0.1
-
- strip-ansi@7.1.0:
- dependencies:
- ansi-regex: 6.1.0
-
- strip-json-comments@3.1.1: {}
-
- sucrase@3.35.0:
- dependencies:
- '@jridgewell/gen-mapping': 0.3.5
- commander: 4.1.1
- glob: 10.4.5
- lines-and-columns: 1.2.4
- mz: 2.7.0
- pirates: 4.0.6
- ts-interface-checker: 0.1.13
-
- supports-color@7.2.0:
- dependencies:
- has-flag: 4.0.0
-
- supports-preserve-symlinks-flag@1.0.0: {}
-
- svelte-check@4.1.0(svelte@5.2.7)(typescript@5.7.2):
- dependencies:
- '@jridgewell/trace-mapping': 0.3.25
- chokidar: 4.0.1
- fdir: 6.4.2
- picocolors: 1.1.1
- sade: 1.8.1
- svelte: 5.2.7
- typescript: 5.7.2
- transitivePeerDependencies:
- - picomatch
-
- svelte-eslint-parser@0.43.0(svelte@5.2.7):
- dependencies:
- eslint-scope: 7.2.2
- eslint-visitor-keys: 3.4.3
- espree: 9.6.1
- postcss: 8.4.49
- postcss-scss: 4.0.9(postcss@8.4.49)
- optionalDependencies:
- svelte: 5.2.7
-
- svelte@5.2.7:
- dependencies:
- '@ampproject/remapping': 2.3.0
- '@jridgewell/sourcemap-codec': 1.5.0
- '@types/estree': 1.0.6
- acorn: 8.14.0
- acorn-typescript: 1.4.13(acorn@8.14.0)
- aria-query: 5.3.2
- axobject-query: 4.1.0
- esm-env: 1.1.4
- esrap: 1.2.2
- is-reference: 3.0.3
- locate-character: 3.0.0
- magic-string: 0.30.13
- zimmerframe: 1.1.2
-
- tailwindcss@3.4.15:
- dependencies:
- '@alloc/quick-lru': 5.2.0
- arg: 5.0.2
- chokidar: 3.6.0
- didyoumean: 1.2.2
- dlv: 1.1.3
- fast-glob: 3.3.2
- glob-parent: 6.0.2
- is-glob: 4.0.3
- jiti: 1.21.6
- lilconfig: 2.1.0
- micromatch: 4.0.8
- normalize-path: 3.0.0
- object-hash: 3.0.0
- picocolors: 1.1.1
- postcss: 8.4.49
- postcss-import: 15.1.0(postcss@8.4.49)
- postcss-js: 4.0.1(postcss@8.4.49)
- postcss-load-config: 4.0.2(postcss@8.4.49)
- postcss-nested: 6.2.0(postcss@8.4.49)
- postcss-selector-parser: 6.1.2
- resolve: 1.22.8
- sucrase: 3.35.0
- transitivePeerDependencies:
- - ts-node
-
- thenify-all@1.6.0:
- dependencies:
- thenify: 3.3.1
-
- thenify@3.3.1:
- dependencies:
- any-promise: 1.3.0
-
- tiny-glob@0.2.9:
- dependencies:
- globalyzer: 0.1.0
- globrex: 0.1.2
-
- to-regex-range@5.0.1:
- dependencies:
- is-number: 7.0.0
-
- totalist@3.0.1: {}
-
- ts-api-utils@1.4.1(typescript@5.7.2):
- dependencies:
- typescript: 5.7.2
-
- ts-interface-checker@0.1.13: {}
-
- type-check@0.4.0:
- dependencies:
- prelude-ls: 1.2.1
-
- typescript-eslint@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- '@typescript-eslint/parser': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- '@typescript-eslint/utils': 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)
- eslint: 9.15.0(jiti@1.21.6)
- optionalDependencies:
- typescript: 5.7.2
- transitivePeerDependencies:
- - supports-color
-
- typescript@5.7.2: {}
-
- unist-util-stringify-position@2.0.3:
- dependencies:
- '@types/unist': 2.0.11
-
- update-browserslist-db@1.1.1(browserslist@4.24.2):
- dependencies:
- browserslist: 4.24.2
- escalade: 3.2.0
- picocolors: 1.1.1
-
- uri-js@4.4.1:
- dependencies:
- punycode: 2.3.1
-
- util-deprecate@1.0.2: {}
-
- vfile-message@2.0.4:
- dependencies:
- '@types/unist': 2.0.11
- unist-util-stringify-position: 2.0.3
-
- vite@5.4.11:
- dependencies:
- esbuild: 0.21.5
- postcss: 8.4.49
- rollup: 4.27.4
- optionalDependencies:
- fsevents: 2.3.3
-
- vitefu@1.0.3(vite@5.4.11):
- optionalDependencies:
- vite: 5.4.11
-
- which@2.0.2:
- dependencies:
- isexe: 2.0.0
-
- word-wrap@1.2.5: {}
-
- wrap-ansi@7.0.0:
- dependencies:
- ansi-styles: 4.3.0
- string-width: 4.2.3
- strip-ansi: 6.0.1
-
- wrap-ansi@8.1.0:
- dependencies:
- ansi-styles: 6.2.1
- string-width: 5.1.2
- strip-ansi: 7.1.0
-
- yaml@1.10.2: {}
-
- yaml@2.6.1: {}
-
- yocto-queue@0.1.0: {}
-
- zimmerframe@1.1.2: {}
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000..a0e70da
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,49 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
+// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
+
+generator client {
+ provider = "prisma-client-js"
+ binaryTargets = ["debian-openssl-1.1.x", "linux-musl-openssl-3.0.x", "linux-musl-arm64-openssl-3.0.x"]
+}
+
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ username String @unique
+ profilePicture String @default("default.png")
+ surname String
+ name String
+ email String @unique
+ password String
+ messages Message[]
+
+ @@map("users") // Table name in DB
+}
+
+model Channel {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String @unique
+ messages Message[]
+ createdAt DateTime @default(now())
+
+ @@map("channels") // Table name in DB
+}
+
+model Message {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ user User @relation(fields: [userId], references: [id])
+ userId String @db.ObjectId
+ channel Channel @relation(fields: [channelId], references: [id])
+ channelId String @db.ObjectId
+ text String
+ createdAt DateTime @default(now())
+
+ @@map("messages") // Table name in DB
+}
diff --git a/src/app.css b/src/app.css
index a31e444..1460463 100644
--- a/src/app.css
+++ b/src/app.css
@@ -1,3 +1,78 @@
-@import 'tailwindcss/base';
-@import 'tailwindcss/components';
-@import 'tailwindcss/utilities';
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --muted: 210 40% 96.1%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 40% 96.1%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --accent: 210 40% 96.1%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 72.2% 50.6%;
+ --destructive-foreground: 210 40% 98%;
+
+ --ring: 222.2 84% 4.9%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 210 40% 98%;
+
+ --ring: 212.7 26.8% 83.9%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
\ No newline at end of file
diff --git a/src/app.d.ts b/src/app.d.ts
index da08e6d..5076ab9 100644
--- a/src/app.d.ts
+++ b/src/app.d.ts
@@ -3,7 +3,10 @@
declare global {
namespace App {
// interface Error {}
- // interface Locals {}
+ interface Locals {
+ token?: string;
+ userId?: string;
+ }
// interface PageData {}
// interface PageState {}
// interface Platform {}
diff --git a/src/hooks.server.ts b/src/hooks.server.ts
new file mode 100644
index 0000000..c4a435b
--- /dev/null
+++ b/src/hooks.server.ts
@@ -0,0 +1,8 @@
+import type { Handle } from '@sveltejs/kit';
+
+export const handle: Handle = async ({ event, resolve }) => {
+ event.locals.token = await event.cookies.get('token');
+ event.locals.userId = await event.cookies.get('UID');
+
+ return await resolve(event);
+};
\ No newline at end of file
diff --git a/src/lib/components/Message.svelte b/src/lib/components/Message.svelte
new file mode 100644
index 0000000..8522f81
--- /dev/null
+++ b/src/lib/components/Message.svelte
@@ -0,0 +1,122 @@
+
+
+{#if user !== null}
+
+
+
+
+
+ {timeElapsed}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {myMessage ? "(Moi)" : ""} {user.username}
+
+
+
+
+
+
+
+ {message.text}
+
+
+
+
+{/if}
+
diff --git a/src/lib/components/ui/Alert.svelte b/src/lib/components/ui/Alert.svelte
new file mode 100644
index 0000000..8b40d1d
--- /dev/null
+++ b/src/lib/components/ui/Alert.svelte
@@ -0,0 +1,66 @@
+
+
+{#if show}
+
+
+ {message}
+
+{/if}
+
+
diff --git a/src/lib/components/ui/ChatItem.svelte b/src/lib/components/ui/ChatItem.svelte
new file mode 100644
index 0000000..fcefea6
--- /dev/null
+++ b/src/lib/components/ui/ChatItem.svelte
@@ -0,0 +1,40 @@
+
+
+
+
+
{title}
+
{lastMessage}
+
+ {timeElapsed}
+
+
+
diff --git a/src/lib/components/ui/ChoosePicture.svelte b/src/lib/components/ui/ChoosePicture.svelte
new file mode 100644
index 0000000..4e08285
--- /dev/null
+++ b/src/lib/components/ui/ChoosePicture.svelte
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+ SĂ©lectionner une image
+
+
+
+
+
+
+ Supprimer l'image
+
+
+
+
+
diff --git a/src/lib/components/ui/CreateChat.svelte b/src/lib/components/ui/CreateChat.svelte
new file mode 100644
index 0000000..4e32b8b
--- /dev/null
+++ b/src/lib/components/ui/CreateChat.svelte
@@ -0,0 +1,97 @@
+
+
+{#if show}
+
+
+
Créer un nouveau chat
+
+
+ Créer
+
+
+
+{/if}
+
+ (showAlert = false)} />
+
+
diff --git a/src/lib/components/ui/ProfileCard.svelte b/src/lib/components/ui/ProfileCard.svelte
new file mode 100644
index 0000000..385e251
--- /dev/null
+++ b/src/lib/components/ui/ProfileCard.svelte
@@ -0,0 +1,139 @@
+
+
+{#if show}
+
+
+
+
+
+ Nom :
+ {user.surname}
+
+
+ Prénom :
+ {user.name}
+
+
+ Email :
+ {user.email}
+
+
+
+ {#if user.id === userSessionId}
+
+ Éditer
+ DĂ©connexion
+
+ {/if}
+
+
+{/if}
+
+
diff --git a/src/lib/components/ui/ProfileInfo.svelte b/src/lib/components/ui/ProfileInfo.svelte
new file mode 100644
index 0000000..e466024
--- /dev/null
+++ b/src/lib/components/ui/ProfileInfo.svelte
@@ -0,0 +1,65 @@
+
+
+{#if show}
+
+
{user.username}
+
{user.email}
+
{user.name} {user.surname}
+
+{/if}
+
+
+
diff --git a/src/lib/components/ui/Search.svelte b/src/lib/components/ui/Search.svelte
new file mode 100644
index 0000000..cec4c25
--- /dev/null
+++ b/src/lib/components/ui/Search.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
+ onChange(event.target.value)}
+ />
+
+
diff --git a/src/lib/components/ui/UserChat.svelte b/src/lib/components/ui/UserChat.svelte
new file mode 100644
index 0000000..27bf7d4
--- /dev/null
+++ b/src/lib/components/ui/UserChat.svelte
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
{user.username}
+
+ {user.state}
+
+
+
+ {#if user.state === "En ligne"}
+
+ {:else if user.state === "Ecrit"}
+
+
+
+
+
+ {/if}
+
+
+
diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte
new file mode 100644
index 0000000..86827f3
--- /dev/null
+++ b/src/lib/components/ui/button/button.svelte
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts
new file mode 100644
index 0000000..af1e188
--- /dev/null
+++ b/src/lib/components/ui/button/index.ts
@@ -0,0 +1,49 @@
+import { type VariantProps, tv } from "tailwind-variants";
+import type { Button as ButtonPrimitive } from "bits-ui";
+import Root from "./button.svelte";
+
+const buttonVariants = tv({
+ base: "ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border-input bg-background hover:bg-accent hover:text-accent-foreground border",
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+});
+
+type Variant = VariantProps["variant"];
+type Size = VariantProps["size"];
+
+type Props = ButtonPrimitive.Props & {
+ variant?: Variant;
+ size?: Size;
+};
+
+type Events = ButtonPrimitive.Events;
+
+export {
+ Root,
+ type Props,
+ type Events,
+ //
+ Root as Button,
+ type Props as ButtonProps,
+ type Events as ButtonEvents,
+ buttonVariants,
+};
diff --git a/src/lib/components/ui/card/card-content.svelte b/src/lib/components/ui/card/card-content.svelte
new file mode 100644
index 0000000..748c644
--- /dev/null
+++ b/src/lib/components/ui/card/card-content.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/card/card-description.svelte b/src/lib/components/ui/card/card-description.svelte
new file mode 100644
index 0000000..f65821d
--- /dev/null
+++ b/src/lib/components/ui/card/card-description.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/card/card-footer.svelte b/src/lib/components/ui/card/card-footer.svelte
new file mode 100644
index 0000000..32f90bb
--- /dev/null
+++ b/src/lib/components/ui/card/card-footer.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/card/card-header.svelte b/src/lib/components/ui/card/card-header.svelte
new file mode 100644
index 0000000..9c65185
--- /dev/null
+++ b/src/lib/components/ui/card/card-header.svelte
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/card/card-title.svelte b/src/lib/components/ui/card/card-title.svelte
new file mode 100644
index 0000000..719808e
--- /dev/null
+++ b/src/lib/components/ui/card/card-title.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/card/card.svelte b/src/lib/components/ui/card/card.svelte
new file mode 100644
index 0000000..b69c15c
--- /dev/null
+++ b/src/lib/components/ui/card/card.svelte
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/card/index.ts b/src/lib/components/ui/card/index.ts
new file mode 100644
index 0000000..bcc031d
--- /dev/null
+++ b/src/lib/components/ui/card/index.ts
@@ -0,0 +1,24 @@
+import Root from "./card.svelte";
+import Content from "./card-content.svelte";
+import Description from "./card-description.svelte";
+import Footer from "./card-footer.svelte";
+import Header from "./card-header.svelte";
+import Title from "./card-title.svelte";
+
+export {
+ Root,
+ Content,
+ Description,
+ Footer,
+ Header,
+ Title,
+ //
+ Root as Card,
+ Content as CardContent,
+ Description as CardDescription,
+ Footer as CardFooter,
+ Header as CardHeader,
+ Title as CardTitle,
+};
+
+export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
diff --git a/src/lib/components/ui/input/index.ts b/src/lib/components/ui/input/index.ts
new file mode 100644
index 0000000..75e3bc2
--- /dev/null
+++ b/src/lib/components/ui/input/index.ts
@@ -0,0 +1,29 @@
+import Root from "./input.svelte";
+
+export type FormInputEvent = T & {
+ currentTarget: EventTarget & HTMLInputElement;
+};
+export type InputEvents = {
+ blur: FormInputEvent;
+ change: FormInputEvent;
+ click: FormInputEvent;
+ focus: FormInputEvent;
+ focusin: FormInputEvent;
+ focusout: FormInputEvent;
+ keydown: FormInputEvent;
+ keypress: FormInputEvent;
+ keyup: FormInputEvent;
+ mouseover: FormInputEvent;
+ mouseenter: FormInputEvent;
+ mouseleave: FormInputEvent;
+ mousemove: FormInputEvent;
+ paste: FormInputEvent;
+ input: FormInputEvent;
+ wheel: FormInputEvent;
+};
+
+export {
+ Root,
+ //
+ Root as Input,
+};
diff --git a/src/lib/components/ui/input/input.svelte b/src/lib/components/ui/input/input.svelte
new file mode 100644
index 0000000..cab1457
--- /dev/null
+++ b/src/lib/components/ui/input/input.svelte
@@ -0,0 +1,42 @@
+
+
+
diff --git a/src/lib/components/ui/label/index.ts b/src/lib/components/ui/label/index.ts
new file mode 100644
index 0000000..8bfca0b
--- /dev/null
+++ b/src/lib/components/ui/label/index.ts
@@ -0,0 +1,7 @@
+import Root from "./label.svelte";
+
+export {
+ Root,
+ //
+ Root as Label,
+};
diff --git a/src/lib/components/ui/label/label.svelte b/src/lib/components/ui/label/label.svelte
new file mode 100644
index 0000000..2a7d479
--- /dev/null
+++ b/src/lib/components/ui/label/label.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/tabs/index.ts b/src/lib/components/ui/tabs/index.ts
new file mode 100644
index 0000000..f1ab372
--- /dev/null
+++ b/src/lib/components/ui/tabs/index.ts
@@ -0,0 +1,18 @@
+import { Tabs as TabsPrimitive } from "bits-ui";
+import Content from "./tabs-content.svelte";
+import List from "./tabs-list.svelte";
+import Trigger from "./tabs-trigger.svelte";
+
+const Root = TabsPrimitive.Root;
+
+export {
+ Root,
+ Content,
+ List,
+ Trigger,
+ //
+ Root as Tabs,
+ Content as TabsContent,
+ List as TabsList,
+ Trigger as TabsTrigger,
+};
diff --git a/src/lib/components/ui/tabs/tabs-content.svelte b/src/lib/components/ui/tabs/tabs-content.svelte
new file mode 100644
index 0000000..b611559
--- /dev/null
+++ b/src/lib/components/ui/tabs/tabs-content.svelte
@@ -0,0 +1,21 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/tabs/tabs-list.svelte b/src/lib/components/ui/tabs/tabs-list.svelte
new file mode 100644
index 0000000..773c754
--- /dev/null
+++ b/src/lib/components/ui/tabs/tabs-list.svelte
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/tabs/tabs-trigger.svelte b/src/lib/components/ui/tabs/tabs-trigger.svelte
new file mode 100644
index 0000000..b99358d
--- /dev/null
+++ b/src/lib/components/ui/tabs/tabs-trigger.svelte
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/src/lib/components/ui/textarea/index.ts b/src/lib/components/ui/textarea/index.ts
new file mode 100644
index 0000000..6eb6ba3
--- /dev/null
+++ b/src/lib/components/ui/textarea/index.ts
@@ -0,0 +1,28 @@
+import Root from "./textarea.svelte";
+
+type FormTextareaEvent = T & {
+ currentTarget: EventTarget & HTMLTextAreaElement;
+};
+
+type TextareaEvents = {
+ blur: FormTextareaEvent;
+ change: FormTextareaEvent;
+ click: FormTextareaEvent;
+ focus: FormTextareaEvent;
+ keydown: FormTextareaEvent;
+ keypress: FormTextareaEvent;
+ keyup: FormTextareaEvent;
+ mouseover: FormTextareaEvent;
+ mouseenter: FormTextareaEvent;
+ mouseleave: FormTextareaEvent;
+ paste: FormTextareaEvent;
+ input: FormTextareaEvent;
+};
+
+export {
+ Root,
+ //
+ Root as Textarea,
+ type TextareaEvents,
+ type FormTextareaEvent,
+};
diff --git a/src/lib/components/ui/textarea/textarea.svelte b/src/lib/components/ui/textarea/textarea.svelte
new file mode 100644
index 0000000..d0da1d4
--- /dev/null
+++ b/src/lib/components/ui/textarea/textarea.svelte
@@ -0,0 +1,38 @@
+
+
+
diff --git a/src/lib/logger.ts b/src/lib/logger.ts
new file mode 100644
index 0000000..9521549
--- /dev/null
+++ b/src/lib/logger.ts
@@ -0,0 +1,21 @@
+import winston from 'winston';
+
+const { combine, timestamp, json, errors } = winston.format;
+
+const logger = winston.createLogger({
+ levels: winston.config.syslog.levels,
+ format: combine(
+ errors({ stack: true }),
+ timestamp(),
+ json(),
+ ),
+ transports: [
+ new winston.transports.Console({level: "debug"}),
+ new winston.transports.File({
+ filename: 'logs/app.log',
+ level: 'debug'
+ })
+ ]
+});
+
+export default logger;
\ No newline at end of file
diff --git a/src/lib/prismaClient.ts b/src/lib/prismaClient.ts
new file mode 100644
index 0000000..031acc8
--- /dev/null
+++ b/src/lib/prismaClient.ts
@@ -0,0 +1,4 @@
+import { PrismaClient } from '@prisma/client';
+
+const prisma = new PrismaClient();
+export default prisma;
\ No newline at end of file
diff --git a/src/lib/redisClient.ts b/src/lib/redisClient.ts
new file mode 100644
index 0000000..62fec25
--- /dev/null
+++ b/src/lib/redisClient.ts
@@ -0,0 +1,16 @@
+import { createClient } from 'redis';
+
+const client = await createClient({
+ url: process.env.REDIS_URL || 'redis://redis-server:6379'
+});
+
+
+client.on('error', (err) => console.error('Redis Error:', err));
+
+try {
+ await client.connect();
+} catch (error) {
+ console.error('Redis Error:', error);
+}
+
+export default client;
diff --git a/src/lib/stores/messagesStore.ts b/src/lib/stores/messagesStore.ts
new file mode 100644
index 0000000..35ae3e5
--- /dev/null
+++ b/src/lib/stores/messagesStore.ts
@@ -0,0 +1,4 @@
+import { writable } from 'svelte/store';
+
+export const messagesStore = writable([]);
+
diff --git a/src/lib/stores/socket.ts b/src/lib/stores/socket.ts
new file mode 100644
index 0000000..9fc02d5
--- /dev/null
+++ b/src/lib/stores/socket.ts
@@ -0,0 +1,9 @@
+import { io } from "socket.io-client";
+
+// Initialisation de la socket
+export const initSocket = () => {
+ const socketInstance = io("http://localhost:5173");
+ let socketId = null;
+
+ return socketInstance
+}
\ No newline at end of file
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..8871245
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,62 @@
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+import { cubicOut } from "svelte/easing";
+import type { TransitionConfig } from "svelte/transition";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+type FlyAndScaleParams = {
+ y?: number;
+ x?: number;
+ start?: number;
+ duration?: number;
+};
+
+export const flyAndScale = (
+ node: Element,
+ params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
+): TransitionConfig => {
+ const style = getComputedStyle(node);
+ const transform = style.transform === "none" ? "" : style.transform;
+
+ const scaleConversion = (
+ valueA: number,
+ scaleA: [number, number],
+ scaleB: [number, number]
+ ) => {
+ const [minA, maxA] = scaleA;
+ const [minB, maxB] = scaleB;
+
+ const percentage = (valueA - minA) / (maxA - minA);
+ const valueB = percentage * (maxB - minB) + minB;
+
+ return valueB;
+ };
+
+ const styleToString = (
+ style: Record
+ ): string => {
+ return Object.keys(style).reduce((str, key) => {
+ if (style[key] === undefined) return str;
+ return str + `${key}:${style[key]};`;
+ }, "");
+ };
+
+ return {
+ duration: params.duration ?? 200,
+ delay: 0,
+ css: (t) => {
+ const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
+ const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
+ const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
+
+ return styleToString({
+ transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
+ opacity: t
+ });
+ },
+ easing: cubicOut
+ };
+};
\ No newline at end of file
diff --git a/src/lib/utils/date.ts b/src/lib/utils/date.ts
new file mode 100644
index 0000000..d83945d
--- /dev/null
+++ b/src/lib/utils/date.ts
@@ -0,0 +1,51 @@
+export function formatDate(dateString) {
+ const date = new Date(dateString);
+ return date.toLocaleString('fr-FR', {
+ day: '2-digit',
+ month: '2-digit',
+ year: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ hour12: false, // format 24 heures
+ });
+}
+
+//fonction qui renvoie le temps depuis la créetion du message à maintenant en fonction du temps on affichera le temps en secondes, minutes, heures, jours, semaines, mois, années
+export function formatDistanceToNow(dateString) {
+ const date = new Date(dateString);
+ const now = new Date();
+ const diff = now - date;
+
+ const seconds = Math.floor(diff / 1000);
+ if (seconds < 60) {
+ return `${seconds} s`;
+ }
+
+ const minutes = Math.floor(seconds / 60);
+ if (minutes < 60) {
+ return `${minutes} min`;
+ }
+
+ const hours = Math.floor(minutes / 60);
+ if (hours < 24) {
+ return `${hours} h`;
+ }
+
+ const days = Math.floor(hours / 24);
+ if (days < 7) {
+ return `${days} j`;
+ }
+
+ const weeks = Math.floor(days / 7);
+ if (weeks < 4) {
+ return `${weeks} sem`;
+ }
+
+ const months = Math.floor(days / 30);
+ if (months < 12) {
+ return `${months} mois`;
+ }
+
+ const years = Math.floor(months / 12);
+ return `${years} ans`;
+}
\ No newline at end of file
diff --git a/src/lib/utils/sort.ts b/src/lib/utils/sort.ts
new file mode 100644
index 0000000..5b31700
--- /dev/null
+++ b/src/lib/utils/sort.ts
@@ -0,0 +1,12 @@
+export function sortChannels(channels) {
+ channels = channels.map((channel) => {
+ return {
+ ...channel,
+ lastUpdate : channel.lastMessage != null ? channel.lastMessage.createdAt : channel.createdAt
+ };
+ });
+
+ return channels.sort((a, b) => {
+ return new Date(b.lastUpdate) - new Date(a.lastUpdate);
+ });
+}
\ No newline at end of file
diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts
new file mode 100644
index 0000000..61c1489
--- /dev/null
+++ b/src/routes/+layout.server.ts
@@ -0,0 +1,24 @@
+import { redirect } from '@sveltejs/kit';
+export async function load({ locals, url, fetch }) {
+
+ const token = locals.token;
+
+ if (token == undefined && url.pathname !== "/") {
+ redirect(301, '/');
+ }
+
+ let user = null;
+ if (locals.userId !== undefined) {
+ const res = await fetch(`/api/users/${locals.userId}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ user = await res.json();
+ }
+
+
+ return { token, user }
+}
\ No newline at end of file
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 9b776b7..a10382a 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -3,4 +3,6 @@
let { children } = $props();
-{@render children()}
+
+ {@render children()}
+
diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts
new file mode 100644
index 0000000..b81dd31
--- /dev/null
+++ b/src/routes/+page.server.ts
@@ -0,0 +1,77 @@
+import { type Actions } from '@sveltejs/kit';
+import { redirect, error, fail } from '@sveltejs/kit';
+import logger from '$lib/logger';
+
+export async function load({locals}) {
+ if (locals.token != undefined) {
+ redirect(302, "/chats")
+ }
+}
+
+export const actions: Actions = {
+ login: async ({request, fetch, cookies}) => {
+ const formData = await request.formData();
+
+ const response = await fetch('/api/auth/login', {
+ method: "POST",
+ body: formData
+ });
+
+ const data = await response.json();
+
+ if (response.ok) {
+ cookies.set('token', data.token, {
+ path: '/',
+ httpOnly: true,
+ sameSite: 'strict',
+ maxAge: (60 * 60) * 30,
+ });
+
+ cookies.set('UID', data.userId, {
+ path: '/',
+ httpOnly: true,
+ sameSite: 'strict',
+ maxAge: (60 * 60) * 30,
+ });
+
+ logger.debug("Successfully created a cookie for the user and proceeded with the login.");
+
+ return redirect(302, "/chats");
+ } else {
+ return fail(400, { error: data.message });
+ }
+ },
+
+ register: async ({request, fetch, cookies}) => {
+ const formData = await request.formData();
+
+ const response = await fetch('/api/auth/register', {
+ method: "POST",
+ body: formData
+ });
+
+ const data = await response.json();
+
+ if (response.ok) {
+ cookies.set('token', data.token, {
+ path: '/',
+ httpOnly: true,
+ sameSite: 'strict',
+ maxAge: (60 * 60) * 30,
+ });
+
+ cookies.set('UID', data.userId, {
+ path: '/',
+ httpOnly: true,
+ sameSite: 'strict',
+ maxAge: (60 * 60) * 30,
+ });
+
+ logger.debug("Successfully created a cookie for the user and proceeded with the register.")
+
+ return redirect(302, "/chats");
+ } else {
+ return fail(400, { error: data.message });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index cc88df0..68eb658 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,2 +1,101 @@
-Welcome to SvelteKit
-Visit svelte.dev/docs/kit to read the documentation
+
+
+
+
+
+
+ Se connecter
+ S'inscrire
+
+
+
+
+
+ {#if random > 8}
+ 🌳 - Arabes
+ {:else}
+ 🌳 - Arbres
+ {/if}
+ Connectez vous pour chatter!
+
+
+
+
+
+
+
+
+ {#if random > 8}
+ 🌳 - Arabes
+ {:else}
+ 🌳 - Arbres
+ {/if}
+ Inscrivez-vous pour chatter!
+
+
+
+
+
+
+
+
+ ($showAlert = false)} />
\ No newline at end of file
diff --git a/src/routes/api/auth/login/+server.ts b/src/routes/api/auth/login/+server.ts
new file mode 100644
index 0000000..69324d1
--- /dev/null
+++ b/src/routes/api/auth/login/+server.ts
@@ -0,0 +1,46 @@
+import prismaClient from '$lib/prismaClient';
+import { error, json } from '@sveltejs/kit';
+import * as argon2 from 'argon2';
+import jwt from 'jsonwebtoken';
+import logger from '$lib/logger';
+
+export async function POST({request}) {
+ const formData = await request.formData();
+
+ // @ts-ignore
+ const email: string = formData.get('email').toString();
+ // @ts-ignore
+ const password: string = formData.get('password').toString();
+
+ const user = await prismaClient.user.findFirst({
+ where: {
+ email: email,
+ }
+ });
+
+ if (user == null) {
+ logger.debug(`Could not find user with email (${email}) in database`);
+ return error(400, {message: "Email ou mot de passe invalide."});
+ }
+
+ logger.debug(`Found user with email (${email}) in database`);
+ try {
+ if (await argon2.verify(user.password, password)) {
+ logger.debug(`Password for user ${user.email} is correct.`);
+ // @ts-ignore
+ const token = jwt.sign(user, process.env.JWT_SECRET, { expiresIn: "1h" });
+ logger.debug(`Generated a JWT token for user ${user.email}.`)
+ return json({token: token, userId: user.id});
+
+ } else {
+ return error(400, {message: "Email ou mot de passe invalide."});
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (e) {
+ logger.error(e);
+ return error(500, {message: e.body.message});
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/routes/api/auth/register/+server.ts b/src/routes/api/auth/register/+server.ts
new file mode 100644
index 0000000..dfbb955
--- /dev/null
+++ b/src/routes/api/auth/register/+server.ts
@@ -0,0 +1,55 @@
+import prismaClient from '$lib/prismaClient';
+import { error, json } from '@sveltejs/kit';
+import * as argon2 from 'argon2';
+import jwt from 'jsonwebtoken';
+import logger from '$lib/logger';
+
+export async function POST({request}) {
+ const formData = await request.formData();
+
+ // @ts-ignore
+ const username: string = formData.get('username').toString().toLowerCase();
+ // @ts-ignore
+ const email: string = formData.get('email').toString().toLowerCase();
+ // @ts-ignore
+ const password: string = formData.get('password').toString();
+
+ const user = await prismaClient.user.findFirst({
+ where: {
+ OR: [
+ { username: username },
+ { email: email },
+ ]
+ }
+ });
+
+ if (user != null) {
+ logger.debug(`A user with email (${email}) already exists in database`);
+ return error(400, {message: "Un compte avec cette adresse email ou nom d'utilisateur existe déjà ."});
+ }
+
+ try {
+ const hash = await argon2.hash(password);
+
+ const newUser = await prismaClient.user.create({
+ data: {
+ username: username,
+ email: email,
+ password: hash,
+ surname: "",
+ name: ""
+ }
+ });
+
+ // @ts-ignore
+ const token = jwt.sign(newUser, process.env.JWT_SECRET, { expiresIn: "1h" });
+ logger.debug(`Generated a JWT token for user ${newUser.email}.`)
+ return json({token: token, userId: newUser.id});
+
+ } catch (e) {
+ logger.error(e);
+ return error(500, {message: "Erreur interne."});
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/routes/api/channels/+server.ts b/src/routes/api/channels/+server.ts
new file mode 100644
index 0000000..f5bf13c
--- /dev/null
+++ b/src/routes/api/channels/+server.ts
@@ -0,0 +1,139 @@
+import { json } from '@sveltejs/kit';
+import prisma from '$lib/prismaClient';
+import redisClient from '$lib/redisClient';
+import logger from '$lib/logger';
+import { sortChannels } from '$lib/utils/sort.ts';
+
+// GET: Liste tous les canaux avec leur premier message
+export async function GET({ url }) {
+ if(url.searchParams.get("name") != null && url.searchParams.get("name") != ""){
+ const name = url.searchParams.get("name");
+ try {
+ let canaux = await prisma.channel.findMany({
+ where: {
+ name: {
+ contains: name,
+ mode: 'insensitive',
+ },
+ },
+ include: {
+ messages: {
+ take: 1, // Récupère le dernier message
+ orderBy: { createdAt: 'desc' },// Trie par date décroissante
+ // as lastMessage not list last message
+ },
+ },
+ });
+
+ canaux = canaux.map((canaux) => {
+ return {
+ ...canaux,
+ lastMessage: canaux.messages.length > 0 ? canaux.messages[0] : null,
+ messages: undefined
+ };
+ });
+
+ canaux = sortChannels(canaux);
+
+ return json(canaux);
+
+ } catch (err) {
+ logger.error(err);
+ return json({ error: 'Erreur serveur' }, { status: 500 });
+ }
+ }else{
+ try {
+
+ let channels = [];
+
+ const cachedChannels = await redisClient.get('channels');
+
+ if (cachedChannels != null) {
+ logger.debug('Cache entry found, fetching channels from cache');
+ channels = JSON.parse(cachedChannels);
+ }else{
+ logger.debug('No cache entry was found, fetching channels from database');
+ }
+ if(channels.length < 10){
+ logger.debug('Fetching channels from database to fill cache');
+ let canaux = await prisma.channel.findMany({
+ include: {
+ messages: {
+ take: 1, // Récupère le dernier message
+ orderBy: { createdAt: 'desc' }, // Trie par date décroissante
+ },
+ },
+ });
+
+ canaux = canaux.map((canaux) => {
+ return {
+ ...canaux,
+ lastMessage: canaux.messages.length > 0 ? canaux.messages[0] : null,
+ messages: undefined
+ };
+ });
+
+ channels = channels.concat(canaux);
+
+ channels = channels.filter((channel, index, self) =>
+ index === self.findIndex((t) => (
+ t.id === channel.id
+ ))
+ );
+
+ channels = sortChannels(channels);
+
+ channels = channels.slice(0, 10);
+
+ await redisClient.set('channels', JSON.stringify(channels), { EX: 3600 });
+ }
+
+ return json(channels);
+
+ } catch (err) {
+ logger.error(err)
+ return json({ error: 'Erreur serveur' }, { status: 500 });
+ }
+ }
+
+}
+
+export async function POST({ request }) {
+ const { name } = await request.json();
+
+ try {
+ let canal = await prisma.channel.create({
+ data: {
+ name
+ },
+ });
+ logger.debug('Creating a new channel in database with id ' + canal.id);
+
+ const cachedChanels = await redisClient.get('channels');
+
+ let channels = cachedChanels != null ? JSON.parse(cachedChanels) : [];
+
+ canal = {
+ ...canal,
+ lastMessage: null,
+ lastUpdate: canal.createdAt,
+ messages: undefined
+ }
+
+ channels.push(canal);
+
+ channels = sortChannels(channels);
+
+ logger.debug(`Added channel (${canal.id}) to channels cache.`);
+ await redisClient.set('channels', JSON.stringify(channels), { EX: 600 });
+
+ return json(canal, { status: 201 });
+
+ } catch (err) {
+ console.log(err);
+ logger.error(err);
+ return json({ error: 'Erreur lors de la création du canal' }, { status: 500 });
+ }
+}
+
+
diff --git a/src/routes/api/channels/[id]/+server.ts b/src/routes/api/channels/[id]/+server.ts
new file mode 100644
index 0000000..e7fa8c8
--- /dev/null
+++ b/src/routes/api/channels/[id]/+server.ts
@@ -0,0 +1,148 @@
+import { json } from '@sveltejs/kit';
+import prisma from '$lib/prismaClient';
+import redisClient from '$lib/redisClient';
+import logger from '$lib/logger';
+
+// Récupérer les informations du canal et le dernier message (avec cache Redis)
+export async function GET({ params }) {
+ const channelId = params.id;
+
+ const channelCacheKey = `channel:${channelId}:info`;
+
+ try {
+ const cachedChannel = await redisClient.get(channelCacheKey);
+ if (cachedChannel) {
+ logger.debug(`Cache entry found, fetching channel (${channelId}) from cache`);
+ return json(JSON.parse(cachedChannel));
+ }
+
+ logger.debug(`No cache entry was found, fetching channel (${channelId}) from database`);
+ const canal = await prisma.channel.findUnique({
+ where: { id: channelId },
+ });
+
+ if (!canal) {
+ logger.debug(`No channel for id ${channelId} was found in database`)
+ return json({ error: 'Canal non trouvé' }, { status: 404 });
+ }
+
+ const lastMessage = await prisma.message.findFirst({
+ where: { id: channelId },
+ orderBy: { createdAt: 'desc' },
+ });
+
+ // Créer un objet combiné pour le canal et le dernier message
+ const canalData = {
+ canal,
+ lastMessage, // Inclure uniquement le dernier message
+ };
+
+
+ const cachedChanels = await redisClient.get('channels');
+ let channels = cachedChanels != null ? JSON.parse(cachedChanels) : [];
+
+ channels.push(canal);
+
+ channels = channels.sort(
+ (
+ a: { messages: { createdAt: Date }[]; createdAt: Date },
+ b: { messages: { createdAt: Date }[]; createdAt: Date }
+ ) => {
+ const lastMessageA = a.messages[0]?.createdAt || a.createdAt ? a.createdAt : new Date();
+ const lastMessageB = b.messages[0]?.createdAt || b.createdAt ? b.createdAt : new Date();
+ return new Date(lastMessageB).getTime() - new Date(lastMessageA).getTime();
+ }
+ );
+
+ logger.debug(`Added channel (${canal.id}) to channels cache.`);
+ await redisClient.set('channels', JSON.stringify(channels), { EX: 600 });
+
+ logger.debug(`Creating a new cache entry with key channel:${channelId}:info`);
+ await redisClient.set(channelCacheKey, JSON.stringify(canalData), {EX: 600, NX: true}); // Cache pendant 5 minutes
+
+
+ return json(canalData);
+ } catch (err) {
+
+ logger.error(err);
+ return json({ error: 'Erreur lors de la récupération du canal ou du dernier message' }, { status: 500 });
+ }
+}
+
+// Supprimer un canal et invalider le cache associé
+export async function DELETE({ params }) {
+ const channelId = params.id;
+
+ try {
+ // Supprimer le canal de la base de données
+ await prisma.channel.delete({
+ where: { id: channelId },
+ });
+ logger.debug(`Deleting channel (${channelId}) from database`);
+
+ logger.debug(`Deleting channel (${channelId}) from cache`);
+ await redisClient.del(`channel:${channelId}:info`);
+
+ return json({ message: 'Canal supprimé avec succès' });
+ } catch (err) {
+ console.error(err);
+ return json({ error: 'Erreur lors de la suppression du canal' }, { status: 500 });
+ }
+}
+
+// Modifier un canal
+export async function PUT({ params, request }) {
+ const channelId = params.id;
+ const { nom } = await request.json();
+
+ // Clé cache pour les informations du canal et le dernier message
+ const canalCacheKey = `channel:${channelId}:info`;
+
+ try {
+ // Mettre à jour les informations du canal dans la base de données
+ const updatedCanal = await prisma.channel.update({
+ where: { id: channelId },
+ data: {
+ name: nom,
+ }
+ });
+
+ // Récupérer le dernier message associé au canal après mise à jour
+ const lastMessage = await prisma.message.findFirst({
+ where: { id: channelId },
+ orderBy: { createdAt: 'desc' },
+ });
+
+ // Créer un objet combiné pour les nouvelles informations du canal et le dernier message
+ const canalData = {
+ canal: updatedCanal,
+ lastMessage, // Inclure uniquement le dernier message
+ };
+
+ const cachedChannels = await redisClient.get('channels');
+ let channelsArrays = cachedChannels != null ? JSON.parse(cachedChannels) : [];
+ channelsArrays = channelsArrays.filter((u: { id: string }) => u.id !== updatedCanal.id);
+ channelsArrays.push(canalData);
+
+ channelsArrays = channelsArrays.sort(
+ (
+ a: { messages: { createdAt: Date }[]; createdAt: Date },
+ b: { messages: { createdAt: Date }[]; createdAt: Date }
+ ) => {
+ const lastMessageA = a.messages[0]?.createdAt || a.createdAt ? a.createdAt : new Date();
+ const lastMessageB = b.messages[0]?.createdAt || b.createdAt ? b.createdAt : new Date();
+ return new Date(lastMessageB).getTime() - new Date(lastMessageA).getTime();
+ }
+ );
+
+ logger.debug(`Updated channel (${channelId}) in channels cache`);
+ await redisClient.set('channels', JSON.stringify(channelsArrays), { EX: 600 })
+ logger.debug(`Updated cache entry with key channel:${channelId}:info`);
+ await redisClient.set(canalCacheKey, JSON.stringify(canalData), { EX: 600, NX: true });
+
+ return json(canalData);
+ } catch (err) {
+ console.error(err);
+ return json({ error: 'Erreur lors de la mise Ă jour du canal' }, { status: 500 });
+ }
+}
diff --git a/src/routes/api/channels/[id]/messages/+server.ts b/src/routes/api/channels/[id]/messages/+server.ts
new file mode 100644
index 0000000..82d3aec
--- /dev/null
+++ b/src/routes/api/channels/[id]/messages/+server.ts
@@ -0,0 +1,197 @@
+import { json } from '@sveltejs/kit';
+import prisma from '$lib/prismaClient';
+import redisClient from '$lib/redisClient';
+import logger from '$lib/logger';
+import { sortChannels } from '$lib/utils/sort.ts';
+
+export async function GET({ params, url }) {
+ const channelId = params.id;
+ logger.debug(`GET /api/channels/${channelId}/messages`);
+
+ const limit = parseInt(url.searchParams.get('limit') || '10');
+ const page = parseInt(url.searchParams.get('page') || '1');
+ const offset = (page - 1) * limit;
+
+ try {
+ logger.debug(`Tentative de récupération des messages du cache pour le channel : ${channelId}`);
+ let redisMessageKeys = await redisClient.zRangeWithScores(
+ `channel:${channelId}:messages`,
+ offset,
+ offset + limit - 1,
+ { REV: true }
+ );
+
+ const redisPipelineRemove = redisClient.multi();
+
+
+ for (const messageKey of redisMessageKeys) {
+ // Vérifie si la clé existe dans Redis
+ const messageKeyValue = messageKey.value;
+ const exists = await redisClient.exists(messageKeyValue);
+ if (!exists) {
+ // Supprime la référence expirée dans le zSet
+ redisPipelineRemove.zRem(`channel:${channelId}:messages`, messageKeyValue);
+ redisMessageKeys = redisMessageKeys.filter((key) => key.value !== messageKeyValue);
+ }
+ }
+ await redisPipelineRemove.exec();
+
+ if (redisMessageKeys.length > 0) {
+ const messages = await Promise.all(
+ redisMessageKeys.map(async (key) => {
+ const message = await redisClient.get(key.value);
+ return JSON.parse(message);
+ })
+ );
+
+ const redisPipeline = redisClient.multi();
+ for (const key of redisMessageKeys) {
+ const message = await redisClient.get(key.value);
+ const msg = JSON.parse(message)
+ redisPipeline.set(key.value, JSON.stringify(msg), {EX: 1800});
+ redisPipeline.zAdd(`channel:${channelId}:messages`, {
+ score: key.score,
+ value: key.value,
+ });
+ }
+ await redisPipeline.exec();
+
+ return json({ limit, page, messages: messages.reverse() });
+ }
+
+ logger.debug(`Aucun message trouvé dans le cache, récupération depuis MongoDB pour le channel : ${channelId}`);
+ const messagesFromDB = await prisma.message.findMany({
+ where: { channelId },
+ select: {
+ id: true,
+ createdAt: true,
+ text: true,
+ user: {
+ select: {
+ id: true,
+ },
+ },
+ },
+ orderBy: { createdAt: 'desc' },
+ skip: offset,
+ take: limit,
+ });
+
+ if (messagesFromDB.length > 0) {
+ const redisPipeline = redisClient.multi();
+ for (const message of messagesFromDB) {
+ const messageKey = `message:${message.id}`;
+ redisPipeline.set(messageKey, JSON.stringify(message), {EX: 1800});
+ redisPipeline.zAdd(`channel:${channelId}:messages`, {
+ score: new Date(message.createdAt).getTime(),
+ value: messageKey,
+ });
+ }
+
+ await redisPipeline.exec();
+ }
+
+ return json({ limit, page, messages: messagesFromDB.reverse() });
+ } catch (err) {
+ logger.error(`Erreur lors de la récupération des messages : ${err.message}`);
+ return json({ error: 'Erreur lors de la récupération des messages' }, { status: 500 });
+ }
+}
+
+export async function POST({ params, request }) {
+ const channelId = params.id;
+ const { userId, text } = await request.json();
+
+ try {
+ // Créer un nouveau message dans MongoDB
+ let newMessage = await prisma.message.create({
+ data: {
+ userId,
+ channelId,
+ text,
+ },
+ select: {
+ id: true,
+ createdAt: true,
+ text: true,
+ user: {
+ select: {
+ id: true,
+ },
+ },
+ channel: {
+ select: {
+ id: true,
+ name: true,
+ },
+ }
+ },
+ });
+
+ // Ajouter le message dans Redis
+ await redisClient.set(`message:${newMessage.id}`, JSON.stringify(newMessage), {EX: 1800});
+ await redisClient.zAdd(`channel:${channelId}:messages`, {
+ score: new Date(newMessage.createdAt).getTime(),
+ value: `message:${newMessage.id}`,
+ });
+
+ //update the channels cache with the new message
+ const cachedChannels = await redisClient.get('channels');
+ let channels = cachedChannels ? JSON.parse(cachedChannels) : [];
+ let channel = channels.find((c) => c.id === channelId);
+ if(channel){
+ channel.lastMessage = {
+ id: newMessage.id,
+ text: newMessage.text,
+ user: newMessage.user,
+ createdAt: newMessage.createdAt,
+ };
+ channel.lastUpdate = newMessage.createdAt;
+ channel.messages = undefined;
+
+ }else{
+ channel = {...newMessage.channel, lastMessage: {
+ id: newMessage.id,
+ text: newMessage.text,
+ user: newMessage.user,
+ createdAt: newMessage.createdAt,
+ }, lastUpdate: newMessage.createdAt, messages: undefined};
+ channels = [channel, ...channels];
+ }
+ await redisClient.set('channels', JSON.stringify(channels), { EX: 600 });
+
+ newMessage.channel = {
+ id: newMessage.channel.id,
+ name: newMessage.channel.name,
+ lastMessage: channel.lastMessage,
+ lastUpdate: channel.lastUpdate,
+ messages: undefined
+ };
+
+ logger.debug(`Nouveau message ajouté pour le channel : ${channelId}`);
+ return json(newMessage, { status: 201 });
+ } catch (err) {
+ logger.error(`Erreur lors de la création du message : ${err.message}`);
+ return json({ error: 'Erreur lors de la création du message' }, { status: 500 });
+ }
+}
+
+export async function DELETE({ params, request }) {
+ const channelId = params.id;
+ const { messageId } = await request.json();
+
+ try {
+ // Supprimer le message dans MongoDB
+ await prisma.message.delete({ where: { id: messageId } });
+
+ // Supprimer le message dans Redis
+ await redisClient.del(`message:${messageId}`);
+ await redisClient.zRem(`channel:${channelId}:messages`, `message:${messageId}`);
+
+ logger.debug(`Message supprimé pour le channel : ${channelId}`);
+ return json({ message: 'Message supprimé avec succès' });
+ } catch (err) {
+ logger.error(`Erreur lors de la suppression du message : ${err.message}`);
+ return json({ error: 'Erreur lors de la suppression du message' }, { status: 500 });
+ }
+}
diff --git a/src/routes/api/users/+server.ts b/src/routes/api/users/+server.ts
new file mode 100644
index 0000000..c5951b5
--- /dev/null
+++ b/src/routes/api/users/+server.ts
@@ -0,0 +1,62 @@
+// src/routes/api/users/+server.js
+import { json } from '@sveltejs/kit';
+import redisClient from '$lib/redisClient';
+import prisma from '$lib/prismaClient';
+import logger from '$lib/logger';
+
+export async function GET() {
+ try {
+ // VĂ©rifier si les utilisateurs sont dans le cache Redis
+ const cachedUsers = await redisClient.get('users');
+ if (cachedUsers) {
+ logger.debug('Cache entry found, fetching users from cache');
+ return json(JSON.parse(cachedUsers));
+ }
+
+ logger.debug('No cache entry was found, fetching users from database');
+ // Sinon, récupérer les utilisateurs depuis MongoDB
+ const users = await prisma.user.findMany();
+
+ // Mettre les utilisateurs en cache
+ logger.debug('Caching users with EX of 600 secs');
+ await redisClient.set('users', JSON.stringify(users), { EX: 600 });
+
+ return json(users);
+ } catch (err) {
+ logger.error(err);
+ return json({ error: 'Erreur serveur' }, { status: 500 });
+ }
+}
+
+export async function POST({ request }) {
+ const { username, surname, name, email, password } = await request.json();
+
+ try {
+ const user = await prisma.user.create({
+ data: {
+ username: username.toLowerCase(),
+ surname,
+ name,
+ email: email.toLowerCase(),
+ password,
+ },
+ });
+ logger.debug('Creating a new user in database with id ' + user.id);
+
+ // Mettre le nouvel utilisateur dans le cache
+ logger.debug(`Caching user (${user.id})`);
+ const cachedUsers = await redisClient.get('users');
+ const usersArray = cachedUsers != null ? JSON.parse(cachedUsers) : [];
+ usersArray.push(user);
+
+ logger.debug(`Added user (${user.id}) to users cache.`);
+ await redisClient.set('users', JSON.stringify(usersArray), { EX: 600 })
+ logger.debug(`Creating a new cache entry with key user:${user.id}, with EX of 3600 secs`);
+ await redisClient.set(`user:${user.id}`, JSON.stringify(user), { EX: 3600 });
+
+ return json(user, { status: 201 });
+ } catch (err) {
+ logger.error(err)
+ return json({ error: 'Erreur lors de la création de l’utilisateur' }, { status: 500 });
+ }
+}
diff --git a/src/routes/api/users/[id]/+server.ts b/src/routes/api/users/[id]/+server.ts
new file mode 100644
index 0000000..594bbab
--- /dev/null
+++ b/src/routes/api/users/[id]/+server.ts
@@ -0,0 +1,136 @@
+import { json } from '@sveltejs/kit';
+import redisClient from '$lib/redisClient';
+import prisma from '$lib/prismaClient';
+import logger from '$lib/logger';
+import { writeFile } from 'node:fs/promises';
+import { extname } from 'path';
+import * as argon2 from 'argon2';
+
+export async function GET({ params }) {
+ const userId = params.id;
+
+ try {
+ // VĂ©rifier si l'utilisateur est dans le cache Redis
+ const cachedUser = await redisClient.get(`user:${userId}`);
+ if (cachedUser) {
+ logger.debug(`Cache entry found, fetching user (${params.id}) from cache`);
+ return json(JSON.parse(cachedUser));
+ }
+
+ logger.debug(`No cache entry was found, fetching user (${params.id}) from database`);
+ // Si non, récupérer depuis MongoDB via Prisma
+ const user = await prisma.user.findUnique({
+ where: { id: userId },
+ });
+
+ if (!user) {
+ logger.debug(`No record of user (${params.id}) found in database`);
+ return json({ error: 'Utilisateur non trouvé' }, { status: 404 });
+ }
+
+ // Mettre l'utilisateur en cache
+ const cachedUsers = await redisClient.get('users');
+ const usersArray = cachedUsers != null ? JSON.parse(cachedUsers) : [];
+ usersArray.push(user);
+ logger.debug(`Added user (${user.id}) to users cache.`);
+ await redisClient.set('users', JSON.stringify(usersArray), { EX: 600 })
+ logger.debug(`Creating a new cache entry with key user:${user.id}, with EX of 3600 secs`);
+ await redisClient.set(`user:${userId}`, JSON.stringify(user), { EX: 3600 });
+
+ return json(user);
+ } catch (err) {
+ logger.error(err);
+ return json({ error: 'Erreur serveur' }, { status: 500 });
+ }
+}
+
+// Mettre Ă jour un utilisateur avec PUT
+export async function PUT({ params, request }) {
+ const userId = params.id;
+ const formData = await request.formData();
+
+ const data: {username?: string, email?: string, surname?: string, name?: string, password?: string, profilePicture?: string} = {};
+
+ // @ts-ignore
+ const username = formData.get('username').toString();
+ // @ts-ignore
+ const surname = formData.get('surname').toString();
+ // @ts-ignore
+ const name = formData.get('name').toString();
+ // @ts-ignore
+ const email = formData.get('email').toString();
+ // @ts-ignore
+ const password = formData?.get('password');
+ // @ts-ignore
+ const profilePicture: File | null = formData?.get('profilePicture');
+
+
+ let filename: string | null = null;
+ if (profilePicture != null) {
+ filename = `${crypto.randomUUID()}${extname(profilePicture?.name)}`;
+ await writeFile(`static/${filename}`, Buffer.from(await profilePicture?.arrayBuffer()));
+ data.profilePicture = filename;
+ }
+
+ if (password != null) {
+ data.password = await argon2.hash(password.toString());
+ }
+
+ data.username = username;
+ data.surname = surname;
+ data.name = name;
+ data.email = email;
+
+
+ try {
+ const updatedUser = await prisma.user.update({
+ where: { id: userId },
+ data: data
+ });
+ logger.debug(`Updated user (${updatedUser.id}) in database`);
+
+ // Mettre Ă jour l'utilisateur dans le cache Redis
+ const cachedUsers = await redisClient.get('users');
+ let usersArray = cachedUsers != null ? JSON.parse(cachedUsers) : [];
+ usersArray = usersArray.filter((u: { id: string }) => u.id !== updatedUser.id);
+ usersArray.push(updatedUser);
+ logger.debug(`Updated user (${updatedUser.id}) in users cache.`);
+ await redisClient.set('users', JSON.stringify(usersArray), { EX: 600 })
+ logger.debug(`Updated cache entry with key user:${updatedUser.id}`);
+ await redisClient.set(`user:${userId}`, JSON.stringify(updatedUser), { EX: 3600 }); // Cache pendant 1 heure (3600 secondes)
+
+ return json(updatedUser);
+ } catch (err) {
+ logger.error(err);
+ return json({ error: 'Erreur lors de la mise à jour de l’utilisateur' }, { status: 500 });
+ }
+}
+
+
+export async function DELETE({ params }) {
+ const userId = params.id;
+
+ try {
+ const deletedUser = await prisma.user.delete({
+ where: { id: userId },
+ });
+ logger.debug(`Deleted user (${deletedUser.id}) from database.`);
+
+ // Supprimer l'utilisateur du cache Redis
+ const cachedUsers = await redisClient.get('users');
+ let usersArray = cachedUsers != null ? JSON.parse(cachedUsers) : [];
+ usersArray = usersArray.filter((u: { id: string }) => u.id !== deletedUser.id);
+ logger.debug(`Deleted cache entry with key user:${deletedUser.id}`);
+ await redisClient.del(`user:${userId}`);
+ logger.debug(`Deleted user (${deletedUser.id}) from users cache.`);
+ await redisClient.set('users', JSON.stringify(usersArray), { EX: 600 })
+
+ return json({ message: 'Utilisateur supprimé avec succès' });
+ } catch (err) {
+ logger.error(err);
+ return json({ error: 'Erreur lors de la suppression de l’utilisateur' }, { status: 500 });
+ }
+}
+
+
+
diff --git a/src/routes/chats/+page.server.ts b/src/routes/chats/+page.server.ts
new file mode 100644
index 0000000..68a3ec2
--- /dev/null
+++ b/src/routes/chats/+page.server.ts
@@ -0,0 +1,25 @@
+export async function load({ fetch, locals }) {
+
+ try {
+ // Appel API ou récupération de données
+ const res = await fetch('/api/channels', {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ const channels = await res.json();
+
+ // Retourner les données à la page sous forme de props
+ return {
+ channels,
+ userId: locals.userId
+ };
+ } catch (error) {
+ console.error('Erreur lors du chargement des canaux:', error);
+ return {
+ channels: [],
+ userId: locals.userId
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/routes/chats/+page.svelte b/src/routes/chats/+page.svelte
new file mode 100644
index 0000000..eb06a54
--- /dev/null
+++ b/src/routes/chats/+page.svelte
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+ Profile
+
+
+
+
+
+
+
+ Nouveau Chat
+
+
+
+
+ {#each channels as channel}
+
+ {/each}
+
+
+
+
+
+
+
diff --git a/src/routes/chats/[id]/+page.server.ts b/src/routes/chats/[id]/+page.server.ts
new file mode 100644
index 0000000..e35b2dc
--- /dev/null
+++ b/src/routes/chats/[id]/+page.server.ts
@@ -0,0 +1,33 @@
+export async function load({ fetch, params, locals }) {
+ try {
+ const res = await fetch(`/api/channels/${params.id}/messages?page=1&limit=10`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ const messages = await res.json();
+ const resUser = await fetch(`/api/users/${locals.userId}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ const user = await resUser.json();
+
+ return {
+ messages,
+ channelId: params.id,
+ userId: locals.userId,
+ user: user
+ }
+ }catch (error) {
+ console.error('Erreur lors du chargement des messages:', error);
+ return {
+ messages: [],
+ channelId: params.id,
+ userId: locals.userId,
+ user: {}
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/routes/chats/[id]/+page.svelte b/src/routes/chats/[id]/+page.svelte
new file mode 100644
index 0000000..1661d6d
--- /dev/null
+++ b/src/routes/chats/[id]/+page.svelte
@@ -0,0 +1,338 @@
+
+
+
+
+
+
+
+ {#each users as u (u.id)}
+ openProfileCard(u)}
+ />
+ {/each}
+
+
+
+
+
+
+
+ {#if isLoading}
+
Chargement...
+ {/if}
+ {#if $messagesStore !== undefined && $messagesStore.length > 0}
+ {#each $messagesStore as message}
+
+ {/each}
+ {:else}
+
SĂ©lectionnez un message le chat est vide.
+ {/if}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/disconnect/+server.ts b/src/routes/disconnect/+server.ts
new file mode 100644
index 0000000..53df5fa
--- /dev/null
+++ b/src/routes/disconnect/+server.ts
@@ -0,0 +1,10 @@
+import { redirect } from '@sveltejs/kit';
+
+export async function POST({ cookies }) {
+ // Supprimer les cookies "token" et "UID"
+ cookies.delete("token", { path: '/' });
+ cookies.delete("UID", { path: '/' });
+
+ // Rediriger vers la page d'accueil ou la page de connexion après déconnexion
+ throw redirect(303, '/');
+}
\ No newline at end of file
diff --git a/src/routes/user/edit/+page.server.ts b/src/routes/user/edit/+page.server.ts
new file mode 100644
index 0000000..ad378bc
--- /dev/null
+++ b/src/routes/user/edit/+page.server.ts
@@ -0,0 +1,23 @@
+export async function load({ fetch, locals }) {
+
+ try {
+ // Appel API ou récupération de données
+ const res = await fetch(`/api/users/${locals.userId}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ });
+ const user = await res.json();
+
+ // Retourner les données à la page sous forme de props
+ return {
+ user
+ };
+ } catch (error) {
+ console.error('Erreur lors du chargement des canaux:', error);
+ return {
+ user : null
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/routes/user/edit/+page.svelte b/src/routes/user/edit/+page.svelte
new file mode 100644
index 0000000..58790bf
--- /dev/null
+++ b/src/routes/user/edit/+page.svelte
@@ -0,0 +1,143 @@
+
+
+
+
+
Modifier les informations du compte
+
+
+ {#if showMessage}
+
+ {message}
+
+ {/if}
+
+
+
+
+
+
+
+
diff --git a/static/default.png b/static/default.png
new file mode 100644
index 0000000..5c9af79
Binary files /dev/null and b/static/default.png differ
diff --git a/static/profile-default.svg b/static/profile-default.svg
new file mode 100644
index 0000000..726ac6f
--- /dev/null
+++ b/static/profile-default.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/svelte.config.js b/svelte.config.js
index 95bf17c..9c9b18b 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -1,5 +1,5 @@
import { mdsvex } from 'mdsvex';
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
@@ -8,11 +8,15 @@ const config = {
// for more information about preprocessors
preprocess: [vitePreprocess(), mdsvex()],
+ alias: {
+ "@/*": "./path/to/lib/*",
+ },
+
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
- adapter: adapter()
+ adapter: adapter(),
},
extensions: ['.svelte', '.svx']
diff --git a/tailwind.config.ts b/tailwind.config.ts
index aa4bc77..c4bf235 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,11 +1,64 @@
-import type { Config } from 'tailwindcss';
-
-export default {
- content: ['./src/**/*.{html,js,svelte,ts}'],
+import { fontFamily } from "tailwindcss/defaultTheme";
+import type { Config } from "tailwindcss";
+const config: Config = {
+ darkMode: ["class"],
+ content: ["./src/**/*.{html,js,svelte,ts}"],
+ safelist: ["dark"],
theme: {
- extend: {}
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px"
+ }
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border) / )",
+ input: "hsl(var(--input) / )",
+ ring: "hsl(var(--ring) / )",
+ background: "hsl(var(--background) / )",
+ foreground: "hsl(var(--foreground) / )",
+ primary: {
+ DEFAULT: "hsl(var(--primary) / )",
+ foreground: "hsl(var(--primary-foreground) / )"
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary) / )",
+ foreground: "hsl(var(--secondary-foreground) / )"
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive) / )",
+ foreground: "hsl(var(--destructive-foreground) / )"
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted) / )",
+ foreground: "hsl(var(--muted-foreground) / )"
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent) / )",
+ foreground: "hsl(var(--accent-foreground) / )"
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover) / )",
+ foreground: "hsl(var(--popover-foreground) / )"
+ },
+ card: {
+ DEFAULT: "hsl(var(--card) / )",
+ foreground: "hsl(var(--card-foreground) / )"
+ }
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)"
+ },
+ fontFamily: {
+ sans: [...fontFamily.sans]
+ }
+ }
},
+};
- plugins: []
-} satisfies Config;
+export default config;
diff --git a/vite.config.ts b/vite.config.ts
index bbf8c7d..ef61386 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,6 +1,87 @@
import { sveltekit } from '@sveltejs/kit/vite';
-import { defineConfig } from 'vite';
+import { type ViteDevServer, defineConfig } from 'vite';
+
+import { Server } from 'socket.io'
+
+function isView(obj) {
+ return obj instanceof DataView || (obj && obj.buffer instanceof ArrayBuffer);
+}
+
+const webSocketServer = {
+ name: 'webSocketServer',
+ configureServer(server: ViteDevServer) {
+ if (!server.httpServer) return
+
+ const io = new Server(server.httpServer)
+
+ let channelsUsers = {};
+
+ io.on('connection', (socket) => {
+ socket.on('new-channel', (channel) => {
+ io.emit('new-channel', channel)
+ });
+
+ // Écouter les messages
+ socket.on('new-message', (message) => {
+ io.emit('new-message', message); // Diffusion du message
+ });
+
+ socket.on('new-user-join', (data) => {
+ const {user, channelId } = data;
+ if (!channelsUsers[channelId]) {
+ channelsUsers[channelId] = [];
+ }
+ if (!channelsUsers[channelId].find((u) => u.id === user.id)) {
+ // Ajouter l'utilisateur Ă la liste des utilisateurs du canal avec son socketId
+ channelsUsers[channelId].push(user);
+ }
+ socket.join(`channel:${channelId}`);
+ io.to(`channel:${channelId}`).emit('load-users-channel', channelsUsers[channelId]);
+ });
+
+ socket.on('leave-channel', (data) => {
+ const { userId, channelId } = data;
+
+ if (channelsUsers[channelId]) {
+ // Supprimez l'utilisateur du canal
+ channelsUsers[channelId] = channelsUsers[channelId].filter((u) => u.id !== userId);
+
+ io.to(`channel:${channelId}`).emit('load-users-channel', channelsUsers[channelId]);
+ console.log(`Utilisateur ${userId} a quitté le canal ${channelId}`);
+ }
+ });
+
+ socket.on('disconnect', () => {
+ console.log('DĂ©connexion du client');
+ for (const channelId in channelsUsers) {
+ channelsUsers[channelId] = channelsUsers[channelId].filter((u) => u.socketId !== socket.id);
+ io.to(`channel:${channelId}`).emit('load-users-channel', channelsUsers[channelId]);
+ }
+ console.log('Utilisateurs connectés:', channelsUsers);
+ });
+
+ socket.on('writing', (data) => {
+ const { userId, channelId } = data;
+ const us = channelsUsers[channelId]?.find((u) => u.id === userId);
+ if (us) {
+ us.state = "Ecrit";
+ io.to(`channel:${channelId}`).emit('user-writing', userId);
+ }
+ });
+
+ socket.on('stop-writing', (data) => {
+ const { userId, channelId } = data;
+ const us = channelsUsers[channelId]?.find((u) => u.id === userId);
+ if (us) {
+ us.state = "En ligne";
+ io.to(`channel:${channelId}`).emit('user-stop-writing', userId);
+ }
+ });
+
+ });
+ }
+}
export default defineConfig({
- plugins: [sveltekit()]
+ plugins: [sveltekit(), webSocketServer]
});