lojol469-cmd commited on
Commit
30d9355
·
1 Parent(s): dc2aa49

Déploiement Kibali UI avec Docker Nginx

Browse files
Files changed (6) hide show
  1. .env +7 -6
  2. Dockerfile +31 -7
  3. package-lock.json +1538 -15
  4. package.json +8 -2
  5. server.js +89 -20
  6. src/App.jsx +274 -54
.env CHANGED
@@ -1,6 +1,7 @@
1
- VITE_FIREBASE_API_KEY=AIzaSyCel4qvAtZomh4aQOCArCLIYSYmeZ4Qbig
2
- VITE_FIREBASE_AUTH_DOMAIN=sevenstatut.firebaseapp.com
3
- VITE_FIREBASE_PROJECT_ID=sevenstatut
4
- VITE_FIREBASE_STORAGE_BUCKET=sevenstatut.firebasestorage.app
5
- VITE_FIREBASE_MESSAGING_SENDER_ID=838268990346
6
- VITE_FIREBASE_APP_ID=1:838268990346:web:dba8702c39e82981704e73
 
 
1
+ VITE_FIREBASE_API_KEY="AIzaSyCel4qvAtZomh4aQOCArCLIYSYmeZ4Qbig"
2
+ VITE_FIREBASE_AUTH_DOMAIN="sevenstatut.firebaseapp.com"
3
+ VITE_FIREBASE_DATABASE_URL="https://sevenstatut-default-rtdb.firebaseio.com"
4
+ VITE_FIREBASE_PROJECT_ID="sevenstatut"
5
+ VITE_FIREBASE_STORAGE_BUCKET="sevenstatut.firebasestorage.app"
6
+ VITE_FIREBASE_MESSAGING_SENDER_ID="838268990346"
7
+ VITE_FIREBASE_APP_ID="1:838268990346:web:dba8702c39e82981704e73"
Dockerfile CHANGED
@@ -1,15 +1,39 @@
1
- # Étape 1 : Build de l'application React
2
- FROM node:18-slim AS build
 
3
  WORKDIR /app
 
 
4
  COPY package*.json ./
5
  RUN npm install
 
 
6
  COPY . .
 
 
7
  RUN npm run build
8
 
9
- # Étape 2 : Serveur de production léger (Nginx)
10
  FROM nginx:stable-alpine
11
- # Copier les fichiers buildés de l'étape précédente vers Nginx
12
- COPY --from=build /app/dist /usr/share/nginx/html
13
- # Exposer le port 80 pour Render
14
- EXPOSE 80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  CMD ["nginx", "-g", "daemon off;"]
 
1
+ # Étape 1 : Construction de l'application
2
+ FROM node:20-slim AS build-stage
3
+
4
  WORKDIR /app
5
+
6
+ # Copie des fichiers de configuration pour le cache des dépendances
7
  COPY package*.json ./
8
  RUN npm install
9
+
10
+ # Copie du reste des fichiers source
11
  COPY . .
12
+
13
+ # Construction du projet (Vite génère le dossier /dist)
14
  RUN npm run build
15
 
16
+ # Étape 2 : Serveur de production Nginx
17
  FROM nginx:stable-alpine
18
+
19
+ # Copie du build vers le dossier que Nginx sert par défaut
20
+ COPY --from=build-stage /app/dist /usr/share/nginx/html
21
+
22
+ # Copie du logo ou des assets spécifiques si nécessaire (optionnel car déjà dans dist)
23
+ # COPY --from=build-stage /app/kibali_logo.svg /usr/share/nginx/html/
24
+
25
+ # Configuration Nginx pour gérer le routage Single Page Application (SPA)
26
+ # HF Spaces utilise souvent le port 7860
27
+ RUN printf 'server {\n\
28
+ listen 7860;\n\
29
+ location / {\n\
30
+ root /usr/share/nginx/html;\n\
31
+ index index.html;\n\
32
+ try_files $uri $uri/ /index.html;\n\
33
+ }\n\
34
+ }' > /etc/nginx/conf.d/default.conf
35
+
36
+ # Exposition du port requis par Hugging Face
37
+ EXPOSE 7860
38
+
39
  CMD ["nginx", "-g", "daemon off;"]
package-lock.json CHANGED
@@ -11,21 +11,27 @@
11
  "@simplewebauthn/browser": "^13.2.2",
12
  "axios": "^1.13.2",
13
  "bcrypt": "^6.0.0",
 
 
 
14
  "cors": "^2.8.5",
15
  "dotenv": "^17.2.3",
16
  "express": "^5.2.1",
17
  "firebase": "^12.7.0",
 
18
  "jsonwebtoken": "^9.0.3",
19
  "leaflet": "^1.9.4",
20
  "lucide-react": "^0.562.0",
21
- "mongoose": "^9.1.0",
22
  "multer": "^2.0.2",
 
23
  "react": "^19.2.0",
24
  "react-dom": "^19.2.0",
25
  "react-leaflet": "^5.0.0",
26
  "react-markdown": "^10.1.0",
27
  "socket.io": "^4.8.3",
28
- "socket.io-client": "^4.8.3"
 
29
  },
30
  "devDependencies": {
31
  "@eslint/js": "^9.39.1",
@@ -923,6 +929,12 @@
923
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
924
  }
925
  },
 
 
 
 
 
 
926
  "node_modules/@firebase/ai": {
927
  "version": "2.6.1",
928
  "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.6.1.tgz",
@@ -1531,6 +1543,94 @@
1531
  "integrity": "sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw==",
1532
  "license": "Apache-2.0"
1533
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1534
  "node_modules/@grpc/grpc-js": {
1535
  "version": "1.9.15",
1536
  "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
@@ -1614,6 +1714,116 @@
1614
  "url": "https://github.com/sponsors/nzakas"
1615
  }
1616
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1617
  "node_modules/@jridgewell/gen-mapping": {
1618
  "version": "0.3.13",
1619
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -1664,6 +1874,17 @@
1664
  "@jridgewell/sourcemap-codec": "^1.4.14"
1665
  }
1666
  },
 
 
 
 
 
 
 
 
 
 
 
1667
  "node_modules/@mongodb-js/saslprep": {
1668
  "version": "1.4.4",
1669
  "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.4.tgz",
@@ -1673,6 +1894,27 @@
1673
  "sparse-bitfield": "^3.0.3"
1674
  }
1675
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1676
  "node_modules/@protobufjs/aspromise": {
1677
  "version": "1.1.2",
1678
  "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
@@ -2075,6 +2317,16 @@
2075
  "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
2076
  "license": "MIT"
2077
  },
 
 
 
 
 
 
 
 
 
 
2078
  "node_modules/@types/babel__core": {
2079
  "version": "7.20.5",
2080
  "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -2120,6 +2372,32 @@
2120
  "@babel/types": "^7.28.2"
2121
  }
2122
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2123
  "node_modules/@types/cors": {
2124
  "version": "2.8.19",
2125
  "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
@@ -2153,6 +2431,30 @@
2153
  "@types/estree": "*"
2154
  }
2155
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2156
  "node_modules/@types/hast": {
2157
  "version": "3.0.4",
2158
  "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
@@ -2162,6 +2464,12 @@
2162
  "@types/unist": "*"
2163
  }
2164
  },
 
 
 
 
 
 
2165
  "node_modules/@types/json-schema": {
2166
  "version": "7.0.15",
2167
  "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -2169,6 +2477,23 @@
2169
  "dev": true,
2170
  "license": "MIT"
2171
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2172
  "node_modules/@types/mdast": {
2173
  "version": "4.0.4",
2174
  "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
@@ -2178,6 +2503,12 @@
2178
  "@types/unist": "*"
2179
  }
2180
  },
 
 
 
 
 
 
2181
  "node_modules/@types/ms": {
2182
  "version": "2.1.0",
2183
  "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
@@ -2193,6 +2524,18 @@
2193
  "undici-types": "~7.16.0"
2194
  }
2195
  },
 
 
 
 
 
 
 
 
 
 
 
 
2196
  "node_modules/@types/react": {
2197
  "version": "19.2.7",
2198
  "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
@@ -2212,6 +2555,74 @@
2212
  "@types/react": "^19.2.0"
2213
  }
2214
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2215
  "node_modules/@types/unist": {
2216
  "version": "3.0.3",
2217
  "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@@ -2260,6 +2671,19 @@
2260
  "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
2261
  }
2262
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
2263
  "node_modules/accepts": {
2264
  "version": "2.0.0",
2265
  "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@@ -2321,6 +2745,15 @@
2321
  "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
2322
  }
2323
  },
 
 
 
 
 
 
 
 
 
2324
  "node_modules/ajv": {
2325
  "version": "6.12.6",
2326
  "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2375,6 +2808,26 @@
2375
  "dev": true,
2376
  "license": "Python-2.0"
2377
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2378
  "node_modules/asynckit": {
2379
  "version": "0.4.0",
2380
  "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -2443,7 +2896,27 @@
2443
  "version": "1.0.2",
2444
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
2445
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
2446
- "dev": true,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2447
  "license": "MIT"
2448
  },
2449
  "node_modules/base64id": {
@@ -2479,6 +2952,24 @@
2479
  "node": ">= 18"
2480
  }
2481
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2482
  "node_modules/body-parser": {
2483
  "version": "2.2.1",
2484
  "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
@@ -2730,6 +3221,19 @@
2730
  "node": ">=12"
2731
  }
2732
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
2733
  "node_modules/color-convert": {
2734
  "version": "2.0.1",
2735
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -2856,7 +3360,7 @@
2856
  "version": "7.0.6",
2857
  "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
2858
  "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
2859
- "dev": true,
2860
  "license": "MIT",
2861
  "dependencies": {
2862
  "path-key": "^3.1.0",
@@ -2873,6 +3377,17 @@
2873
  "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
2874
  "license": "MIT"
2875
  },
 
 
 
 
 
 
 
 
 
 
 
2876
  "node_modules/debug": {
2877
  "version": "4.4.3",
2878
  "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -2976,6 +3491,27 @@
2976
  "node": ">= 0.4"
2977
  }
2978
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2979
  "node_modules/ecdsa-sig-formatter": {
2980
  "version": "1.0.11",
2981
  "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
@@ -3013,6 +3549,16 @@
3013
  "node": ">= 0.8"
3014
  }
3015
  },
 
 
 
 
 
 
 
 
 
 
3016
  "node_modules/engine.io": {
3017
  "version": "6.6.5",
3018
  "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz",
@@ -3395,6 +3941,16 @@
3395
  "node": ">= 0.6"
3396
  }
3397
  },
 
 
 
 
 
 
 
 
 
 
3398
  "node_modules/express": {
3399
  "version": "5.2.1",
3400
  "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
@@ -3469,11 +4025,19 @@
3469
  "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
3470
  "license": "MIT"
3471
  },
 
 
 
 
 
 
 
 
 
3472
  "node_modules/fast-deep-equal": {
3473
  "version": "3.1.3",
3474
  "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
3475
  "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
3476
- "dev": true,
3477
  "license": "MIT"
3478
  },
3479
  "node_modules/fast-json-stable-stringify": {
@@ -3490,6 +4054,25 @@
3490
  "dev": true,
3491
  "license": "MIT"
3492
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3493
  "node_modules/faye-websocket": {
3494
  "version": "0.11.4",
3495
  "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
@@ -3520,6 +4103,31 @@
3520
  }
3521
  }
3522
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3523
  "node_modules/file-entry-cache": {
3524
  "version": "8.0.0",
3525
  "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -3607,6 +4215,47 @@
3607
  "@firebase/util": "1.13.0"
3608
  }
3609
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3610
  "node_modules/flat-cache": {
3611
  "version": "4.0.1",
3612
  "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
@@ -3648,6 +4297,24 @@
3648
  }
3649
  }
3650
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3651
  "node_modules/form-data": {
3652
  "version": "4.0.5",
3653
  "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
@@ -3664,6 +4331,20 @@
3664
  "node": ">= 6"
3665
  }
3666
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3667
  "node_modules/forwarded": {
3668
  "version": "0.2.0",
3669
  "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -3720,6 +4401,95 @@
3720
  "url": "https://github.com/sponsors/ljharb"
3721
  }
3722
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3723
  "node_modules/gensync": {
3724
  "version": "1.0.0-beta.2",
3725
  "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -3776,6 +4546,28 @@
3776
  "node": ">= 0.4"
3777
  }
3778
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3779
  "node_modules/glob-parent": {
3780
  "version": "6.0.2",
3781
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -3789,6 +4581,34 @@
3789
  "node": ">=10.13.0"
3790
  }
3791
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3792
  "node_modules/globals": {
3793
  "version": "16.5.0",
3794
  "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
@@ -3802,6 +4622,128 @@
3802
  "url": "https://github.com/sponsors/sindresorhus"
3803
  }
3804
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3805
  "node_modules/gopd": {
3806
  "version": "1.2.0",
3807
  "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -3814,6 +4756,19 @@
3814
  "url": "https://github.com/sponsors/ljharb"
3815
  }
3816
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
3817
  "node_modules/has-flag": {
3818
  "version": "4.0.0",
3819
  "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -3920,6 +4875,23 @@
3920
  "hermes-estree": "0.25.1"
3921
  }
3922
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3923
  "node_modules/html-url-attributes": {
3924
  "version": "3.0.1",
3925
  "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
@@ -3956,6 +4928,47 @@
3956
  "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
3957
  "license": "MIT"
3958
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3959
  "node_modules/iconv-lite": {
3960
  "version": "0.7.1",
3961
  "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
@@ -4130,13 +5143,51 @@
4130
  "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
4131
  "license": "MIT"
4132
  },
 
 
 
 
 
 
 
 
 
 
 
 
4133
  "node_modules/isexe": {
4134
  "version": "2.0.0",
4135
  "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
4136
  "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
4137
- "dev": true,
4138
  "license": "ISC"
4139
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4140
  "node_modules/js-tokens": {
4141
  "version": "4.0.0",
4142
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -4170,6 +5221,15 @@
4170
  "node": ">=6"
4171
  }
4172
  },
 
 
 
 
 
 
 
 
 
4173
  "node_modules/json-buffer": {
4174
  "version": "3.0.1",
4175
  "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -4249,6 +5309,23 @@
4249
  "safe-buffer": "^5.0.1"
4250
  }
4251
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4252
  "node_modules/jws": {
4253
  "version": "4.0.1",
4254
  "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
@@ -4298,6 +5375,11 @@
4298
  "node": ">= 0.8.0"
4299
  }
4300
  },
 
 
 
 
 
4301
  "node_modules/locate-path": {
4302
  "version": "6.0.0",
4303
  "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -4314,12 +5396,24 @@
4314
  "url": "https://github.com/sponsors/sindresorhus"
4315
  }
4316
  },
 
 
 
 
 
 
4317
  "node_modules/lodash.camelcase": {
4318
  "version": "4.3.0",
4319
  "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
4320
  "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
4321
  "license": "MIT"
4322
  },
 
 
 
 
 
 
4323
  "node_modules/lodash.includes": {
4324
  "version": "4.3.0",
4325
  "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -4395,6 +5489,34 @@
4395
  "yallist": "^3.0.2"
4396
  }
4397
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4398
  "node_modules/lucide-react": {
4399
  "version": "0.562.0",
4400
  "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz",
@@ -5035,6 +6157,19 @@
5035
  ],
5036
  "license": "MIT"
5037
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
5038
  "node_modules/mime-db": {
5039
  "version": "1.52.0",
5040
  "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -5078,6 +6213,17 @@
5078
  "url": "https://github.com/sponsors/ljharb"
5079
  }
5080
  },
 
 
 
 
 
 
 
 
 
 
 
5081
  "node_modules/mkdirp": {
5082
  "version": "0.5.6",
5083
  "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
@@ -5150,9 +6296,9 @@
5150
  }
5151
  },
5152
  "node_modules/mongoose": {
5153
- "version": "9.1.0",
5154
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.1.0.tgz",
5155
- "integrity": "sha512-RVCApwqD6q+O3rsnypmiL1K5+mkN5DwA7BO5a5ofCKh/EZB9FKvcQ4EiqHNmRye3cXhz5DmQ/aVyfBFkXnUbrg==",
5156
  "license": "MIT",
5157
  "dependencies": {
5158
  "kareem": "3.0.0",
@@ -5278,6 +6424,79 @@
5278
  "node": "^18 || ^20 || >= 21"
5279
  }
5280
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5281
  "node_modules/node-gyp-build": {
5282
  "version": "4.8.4",
5283
  "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
@@ -5296,6 +6515,15 @@
5296
  "dev": true,
5297
  "license": "MIT"
5298
  },
 
 
 
 
 
 
 
 
 
5299
  "node_modules/object-assign": {
5300
  "version": "4.1.1",
5301
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -5305,6 +6533,16 @@
5305
  "node": ">=0.10.0"
5306
  }
5307
  },
 
 
 
 
 
 
 
 
 
 
5308
  "node_modules/object-inspect": {
5309
  "version": "1.13.4",
5310
  "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -5360,7 +6598,7 @@
5360
  "version": "3.1.0",
5361
  "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
5362
  "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
5363
- "dev": true,
5364
  "license": "MIT",
5365
  "dependencies": {
5366
  "yocto-queue": "^0.1.0"
@@ -5388,6 +6626,14 @@
5388
  "url": "https://github.com/sponsors/sindresorhus"
5389
  }
5390
  },
 
 
 
 
 
 
 
 
5391
  "node_modules/parent-module": {
5392
  "version": "1.0.1",
5393
  "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -5449,12 +6695,38 @@
5449
  "version": "3.1.1",
5450
  "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
5451
  "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
5452
- "dev": true,
5453
  "license": "MIT",
5454
  "engines": {
5455
  "node": ">=8"
5456
  }
5457
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5458
  "node_modules/path-to-regexp": {
5459
  "version": "8.3.0",
5460
  "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
@@ -5541,6 +6813,19 @@
5541
  "url": "https://github.com/sponsors/wooorm"
5542
  }
5543
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
5544
  "node_modules/protobufjs": {
5545
  "version": "7.5.4",
5546
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
@@ -5593,6 +6878,17 @@
5593
  "node": ">=6"
5594
  }
5595
  },
 
 
 
 
 
 
 
 
 
 
 
5596
  "node_modules/qs": {
5597
  "version": "6.14.1",
5598
  "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
@@ -5770,6 +7066,48 @@
5770
  "node": ">=4"
5771
  }
5772
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5773
  "node_modules/rollup": {
5774
  "version": "4.54.0",
5775
  "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz",
@@ -5950,7 +7288,7 @@
5950
  "version": "2.0.0",
5951
  "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
5952
  "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
5953
- "dev": true,
5954
  "license": "MIT",
5955
  "dependencies": {
5956
  "shebang-regex": "^3.0.0"
@@ -5963,7 +7301,7 @@
5963
  "version": "3.0.0",
5964
  "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
5965
  "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
5966
- "dev": true,
5967
  "license": "MIT",
5968
  "engines": {
5969
  "node": ">=8"
@@ -6047,6 +7385,20 @@
6047
  "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==",
6048
  "license": "MIT"
6049
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6050
  "node_modules/socket.io": {
6051
  "version": "4.8.3",
6052
  "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz",
@@ -6163,6 +7515,23 @@
6163
  "node": ">= 0.8"
6164
  }
6165
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6166
  "node_modules/streamsearch": {
6167
  "version": "1.1.0",
6168
  "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
@@ -6194,6 +7563,23 @@
6194
  "node": ">=8"
6195
  }
6196
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6197
  "node_modules/stringify-entities": {
6198
  "version": "4.0.4",
6199
  "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
@@ -6220,6 +7606,21 @@
6220
  "node": ">=8"
6221
  }
6222
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6223
  "node_modules/strip-json-comments": {
6224
  "version": "3.1.1",
6225
  "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -6233,6 +7634,26 @@
6233
  "url": "https://github.com/sponsors/sindresorhus"
6234
  }
6235
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6236
  "node_modules/style-to-js": {
6237
  "version": "1.1.21",
6238
  "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
@@ -6271,6 +7692,64 @@
6271
  "dev": true,
6272
  "license": "MIT"
6273
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6274
  "node_modules/tinyglobby": {
6275
  "version": "0.2.15",
6276
  "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
@@ -6542,6 +8021,19 @@
6542
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
6543
  "license": "MIT"
6544
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
6545
  "node_modules/vary": {
6546
  "version": "1.1.2",
6547
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -6654,6 +8146,17 @@
6654
  }
6655
  }
6656
  },
 
 
 
 
 
 
 
 
 
 
 
6657
  "node_modules/web-vitals": {
6658
  "version": "4.2.4",
6659
  "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
@@ -6709,7 +8212,7 @@
6709
  "version": "2.0.2",
6710
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
6711
  "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
6712
- "dev": true,
6713
  "license": "ISC",
6714
  "dependencies": {
6715
  "isexe": "^2.0.0"
@@ -6748,6 +8251,26 @@
6748
  "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
6749
  }
6750
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6751
  "node_modules/wrappy": {
6752
  "version": "1.0.2",
6753
  "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -6839,7 +8362,7 @@
6839
  "version": "0.1.0",
6840
  "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
6841
  "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
6842
- "dev": true,
6843
  "license": "MIT",
6844
  "engines": {
6845
  "node": ">=10"
 
11
  "@simplewebauthn/browser": "^13.2.2",
12
  "axios": "^1.13.2",
13
  "bcrypt": "^6.0.0",
14
+ "bcryptjs": "^3.0.3",
15
+ "body-parser": "^2.2.1",
16
+ "cloudinary": "^2.8.0",
17
  "cors": "^2.8.5",
18
  "dotenv": "^17.2.3",
19
  "express": "^5.2.1",
20
  "firebase": "^12.7.0",
21
+ "firebase-admin": "^13.6.0",
22
  "jsonwebtoken": "^9.0.3",
23
  "leaflet": "^1.9.4",
24
  "lucide-react": "^0.562.0",
25
+ "mongoose": "^9.1.1",
26
  "multer": "^2.0.2",
27
+ "nodemailer": "^7.0.12",
28
  "react": "^19.2.0",
29
  "react-dom": "^19.2.0",
30
  "react-leaflet": "^5.0.0",
31
  "react-markdown": "^10.1.0",
32
  "socket.io": "^4.8.3",
33
+ "socket.io-client": "^4.8.3",
34
+ "ws": "^8.18.3"
35
  },
36
  "devDependencies": {
37
  "@eslint/js": "^9.39.1",
 
929
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
930
  }
931
  },
932
+ "node_modules/@fastify/busboy": {
933
+ "version": "3.2.0",
934
+ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz",
935
+ "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==",
936
+ "license": "MIT"
937
+ },
938
  "node_modules/@firebase/ai": {
939
  "version": "2.6.1",
940
  "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.6.1.tgz",
 
1543
  "integrity": "sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw==",
1544
  "license": "Apache-2.0"
1545
  },
1546
+ "node_modules/@google-cloud/firestore": {
1547
+ "version": "7.11.6",
1548
+ "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.6.tgz",
1549
+ "integrity": "sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==",
1550
+ "license": "Apache-2.0",
1551
+ "optional": true,
1552
+ "dependencies": {
1553
+ "@opentelemetry/api": "^1.3.0",
1554
+ "fast-deep-equal": "^3.1.1",
1555
+ "functional-red-black-tree": "^1.0.1",
1556
+ "google-gax": "^4.3.3",
1557
+ "protobufjs": "^7.2.6"
1558
+ },
1559
+ "engines": {
1560
+ "node": ">=14.0.0"
1561
+ }
1562
+ },
1563
+ "node_modules/@google-cloud/paginator": {
1564
+ "version": "5.0.2",
1565
+ "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz",
1566
+ "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==",
1567
+ "license": "Apache-2.0",
1568
+ "optional": true,
1569
+ "dependencies": {
1570
+ "arrify": "^2.0.0",
1571
+ "extend": "^3.0.2"
1572
+ },
1573
+ "engines": {
1574
+ "node": ">=14.0.0"
1575
+ }
1576
+ },
1577
+ "node_modules/@google-cloud/projectify": {
1578
+ "version": "4.0.0",
1579
+ "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz",
1580
+ "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==",
1581
+ "license": "Apache-2.0",
1582
+ "optional": true,
1583
+ "engines": {
1584
+ "node": ">=14.0.0"
1585
+ }
1586
+ },
1587
+ "node_modules/@google-cloud/promisify": {
1588
+ "version": "4.0.0",
1589
+ "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz",
1590
+ "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==",
1591
+ "license": "Apache-2.0",
1592
+ "optional": true,
1593
+ "engines": {
1594
+ "node": ">=14"
1595
+ }
1596
+ },
1597
+ "node_modules/@google-cloud/storage": {
1598
+ "version": "7.18.0",
1599
+ "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.18.0.tgz",
1600
+ "integrity": "sha512-r3ZwDMiz4nwW6R922Z1pwpePxyRwE5GdevYX63hRmAQUkUQJcBH/79EnQPDv5cOv1mFBgevdNWQfi3tie3dHrQ==",
1601
+ "license": "Apache-2.0",
1602
+ "optional": true,
1603
+ "dependencies": {
1604
+ "@google-cloud/paginator": "^5.0.0",
1605
+ "@google-cloud/projectify": "^4.0.0",
1606
+ "@google-cloud/promisify": "<4.1.0",
1607
+ "abort-controller": "^3.0.0",
1608
+ "async-retry": "^1.3.3",
1609
+ "duplexify": "^4.1.3",
1610
+ "fast-xml-parser": "^4.4.1",
1611
+ "gaxios": "^6.0.2",
1612
+ "google-auth-library": "^9.6.3",
1613
+ "html-entities": "^2.5.2",
1614
+ "mime": "^3.0.0",
1615
+ "p-limit": "^3.0.1",
1616
+ "retry-request": "^7.0.0",
1617
+ "teeny-request": "^9.0.0",
1618
+ "uuid": "^8.0.0"
1619
+ },
1620
+ "engines": {
1621
+ "node": ">=14"
1622
+ }
1623
+ },
1624
+ "node_modules/@google-cloud/storage/node_modules/uuid": {
1625
+ "version": "8.3.2",
1626
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
1627
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
1628
+ "license": "MIT",
1629
+ "optional": true,
1630
+ "bin": {
1631
+ "uuid": "dist/bin/uuid"
1632
+ }
1633
+ },
1634
  "node_modules/@grpc/grpc-js": {
1635
  "version": "1.9.15",
1636
  "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
 
1714
  "url": "https://github.com/sponsors/nzakas"
1715
  }
1716
  },
1717
+ "node_modules/@isaacs/cliui": {
1718
+ "version": "8.0.2",
1719
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
1720
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
1721
+ "license": "ISC",
1722
+ "optional": true,
1723
+ "peer": true,
1724
+ "dependencies": {
1725
+ "string-width": "^5.1.2",
1726
+ "string-width-cjs": "npm:string-width@^4.2.0",
1727
+ "strip-ansi": "^7.0.1",
1728
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
1729
+ "wrap-ansi": "^8.1.0",
1730
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
1731
+ },
1732
+ "engines": {
1733
+ "node": ">=12"
1734
+ }
1735
+ },
1736
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
1737
+ "version": "6.2.2",
1738
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
1739
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
1740
+ "license": "MIT",
1741
+ "optional": true,
1742
+ "peer": true,
1743
+ "engines": {
1744
+ "node": ">=12"
1745
+ },
1746
+ "funding": {
1747
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
1748
+ }
1749
+ },
1750
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
1751
+ "version": "6.2.3",
1752
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
1753
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
1754
+ "license": "MIT",
1755
+ "optional": true,
1756
+ "peer": true,
1757
+ "engines": {
1758
+ "node": ">=12"
1759
+ },
1760
+ "funding": {
1761
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1762
+ }
1763
+ },
1764
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
1765
+ "version": "9.2.2",
1766
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
1767
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
1768
+ "license": "MIT",
1769
+ "optional": true,
1770
+ "peer": true
1771
+ },
1772
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
1773
+ "version": "5.1.2",
1774
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
1775
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
1776
+ "license": "MIT",
1777
+ "optional": true,
1778
+ "peer": true,
1779
+ "dependencies": {
1780
+ "eastasianwidth": "^0.2.0",
1781
+ "emoji-regex": "^9.2.2",
1782
+ "strip-ansi": "^7.0.1"
1783
+ },
1784
+ "engines": {
1785
+ "node": ">=12"
1786
+ },
1787
+ "funding": {
1788
+ "url": "https://github.com/sponsors/sindresorhus"
1789
+ }
1790
+ },
1791
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
1792
+ "version": "7.1.2",
1793
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
1794
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
1795
+ "license": "MIT",
1796
+ "optional": true,
1797
+ "peer": true,
1798
+ "dependencies": {
1799
+ "ansi-regex": "^6.0.1"
1800
+ },
1801
+ "engines": {
1802
+ "node": ">=12"
1803
+ },
1804
+ "funding": {
1805
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
1806
+ }
1807
+ },
1808
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
1809
+ "version": "8.1.0",
1810
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
1811
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
1812
+ "license": "MIT",
1813
+ "optional": true,
1814
+ "peer": true,
1815
+ "dependencies": {
1816
+ "ansi-styles": "^6.1.0",
1817
+ "string-width": "^5.0.1",
1818
+ "strip-ansi": "^7.0.1"
1819
+ },
1820
+ "engines": {
1821
+ "node": ">=12"
1822
+ },
1823
+ "funding": {
1824
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1825
+ }
1826
+ },
1827
  "node_modules/@jridgewell/gen-mapping": {
1828
  "version": "0.3.13",
1829
  "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
 
1874
  "@jridgewell/sourcemap-codec": "^1.4.14"
1875
  }
1876
  },
1877
+ "node_modules/@js-sdsl/ordered-map": {
1878
+ "version": "4.4.2",
1879
+ "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
1880
+ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
1881
+ "license": "MIT",
1882
+ "optional": true,
1883
+ "funding": {
1884
+ "type": "opencollective",
1885
+ "url": "https://opencollective.com/js-sdsl"
1886
+ }
1887
+ },
1888
  "node_modules/@mongodb-js/saslprep": {
1889
  "version": "1.4.4",
1890
  "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.4.tgz",
 
1894
  "sparse-bitfield": "^3.0.3"
1895
  }
1896
  },
1897
+ "node_modules/@opentelemetry/api": {
1898
+ "version": "1.9.0",
1899
+ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
1900
+ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
1901
+ "license": "Apache-2.0",
1902
+ "optional": true,
1903
+ "engines": {
1904
+ "node": ">=8.0.0"
1905
+ }
1906
+ },
1907
+ "node_modules/@pkgjs/parseargs": {
1908
+ "version": "0.11.0",
1909
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
1910
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
1911
+ "license": "MIT",
1912
+ "optional": true,
1913
+ "peer": true,
1914
+ "engines": {
1915
+ "node": ">=14"
1916
+ }
1917
+ },
1918
  "node_modules/@protobufjs/aspromise": {
1919
  "version": "1.1.2",
1920
  "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
 
2317
  "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
2318
  "license": "MIT"
2319
  },
2320
+ "node_modules/@tootallnate/once": {
2321
+ "version": "2.0.0",
2322
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
2323
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
2324
+ "license": "MIT",
2325
+ "optional": true,
2326
+ "engines": {
2327
+ "node": ">= 10"
2328
+ }
2329
+ },
2330
  "node_modules/@types/babel__core": {
2331
  "version": "7.20.5",
2332
  "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
 
2372
  "@babel/types": "^7.28.2"
2373
  }
2374
  },
2375
+ "node_modules/@types/body-parser": {
2376
+ "version": "1.19.6",
2377
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
2378
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
2379
+ "license": "MIT",
2380
+ "dependencies": {
2381
+ "@types/connect": "*",
2382
+ "@types/node": "*"
2383
+ }
2384
+ },
2385
+ "node_modules/@types/caseless": {
2386
+ "version": "0.12.5",
2387
+ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
2388
+ "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==",
2389
+ "license": "MIT",
2390
+ "optional": true
2391
+ },
2392
+ "node_modules/@types/connect": {
2393
+ "version": "3.4.38",
2394
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
2395
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
2396
+ "license": "MIT",
2397
+ "dependencies": {
2398
+ "@types/node": "*"
2399
+ }
2400
+ },
2401
  "node_modules/@types/cors": {
2402
  "version": "2.8.19",
2403
  "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
 
2431
  "@types/estree": "*"
2432
  }
2433
  },
2434
+ "node_modules/@types/express": {
2435
+ "version": "4.17.25",
2436
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
2437
+ "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
2438
+ "license": "MIT",
2439
+ "dependencies": {
2440
+ "@types/body-parser": "*",
2441
+ "@types/express-serve-static-core": "^4.17.33",
2442
+ "@types/qs": "*",
2443
+ "@types/serve-static": "^1"
2444
+ }
2445
+ },
2446
+ "node_modules/@types/express-serve-static-core": {
2447
+ "version": "4.19.7",
2448
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz",
2449
+ "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==",
2450
+ "license": "MIT",
2451
+ "dependencies": {
2452
+ "@types/node": "*",
2453
+ "@types/qs": "*",
2454
+ "@types/range-parser": "*",
2455
+ "@types/send": "*"
2456
+ }
2457
+ },
2458
  "node_modules/@types/hast": {
2459
  "version": "3.0.4",
2460
  "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
 
2464
  "@types/unist": "*"
2465
  }
2466
  },
2467
+ "node_modules/@types/http-errors": {
2468
+ "version": "2.0.5",
2469
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
2470
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
2471
+ "license": "MIT"
2472
+ },
2473
  "node_modules/@types/json-schema": {
2474
  "version": "7.0.15",
2475
  "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
 
2477
  "dev": true,
2478
  "license": "MIT"
2479
  },
2480
+ "node_modules/@types/jsonwebtoken": {
2481
+ "version": "9.0.10",
2482
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
2483
+ "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
2484
+ "license": "MIT",
2485
+ "dependencies": {
2486
+ "@types/ms": "*",
2487
+ "@types/node": "*"
2488
+ }
2489
+ },
2490
+ "node_modules/@types/long": {
2491
+ "version": "4.0.2",
2492
+ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
2493
+ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==",
2494
+ "license": "MIT",
2495
+ "optional": true
2496
+ },
2497
  "node_modules/@types/mdast": {
2498
  "version": "4.0.4",
2499
  "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
 
2503
  "@types/unist": "*"
2504
  }
2505
  },
2506
+ "node_modules/@types/mime": {
2507
+ "version": "1.3.5",
2508
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
2509
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
2510
+ "license": "MIT"
2511
+ },
2512
  "node_modules/@types/ms": {
2513
  "version": "2.1.0",
2514
  "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
 
2524
  "undici-types": "~7.16.0"
2525
  }
2526
  },
2527
+ "node_modules/@types/qs": {
2528
+ "version": "6.14.0",
2529
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
2530
+ "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
2531
+ "license": "MIT"
2532
+ },
2533
+ "node_modules/@types/range-parser": {
2534
+ "version": "1.2.7",
2535
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
2536
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
2537
+ "license": "MIT"
2538
+ },
2539
  "node_modules/@types/react": {
2540
  "version": "19.2.7",
2541
  "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
 
2555
  "@types/react": "^19.2.0"
2556
  }
2557
  },
2558
+ "node_modules/@types/request": {
2559
+ "version": "2.48.13",
2560
+ "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz",
2561
+ "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==",
2562
+ "license": "MIT",
2563
+ "optional": true,
2564
+ "dependencies": {
2565
+ "@types/caseless": "*",
2566
+ "@types/node": "*",
2567
+ "@types/tough-cookie": "*",
2568
+ "form-data": "^2.5.5"
2569
+ }
2570
+ },
2571
+ "node_modules/@types/request/node_modules/form-data": {
2572
+ "version": "2.5.5",
2573
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz",
2574
+ "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==",
2575
+ "license": "MIT",
2576
+ "optional": true,
2577
+ "dependencies": {
2578
+ "asynckit": "^0.4.0",
2579
+ "combined-stream": "^1.0.8",
2580
+ "es-set-tostringtag": "^2.1.0",
2581
+ "hasown": "^2.0.2",
2582
+ "mime-types": "^2.1.35",
2583
+ "safe-buffer": "^5.2.1"
2584
+ },
2585
+ "engines": {
2586
+ "node": ">= 0.12"
2587
+ }
2588
+ },
2589
+ "node_modules/@types/send": {
2590
+ "version": "1.2.1",
2591
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
2592
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
2593
+ "license": "MIT",
2594
+ "dependencies": {
2595
+ "@types/node": "*"
2596
+ }
2597
+ },
2598
+ "node_modules/@types/serve-static": {
2599
+ "version": "1.15.10",
2600
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
2601
+ "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
2602
+ "license": "MIT",
2603
+ "dependencies": {
2604
+ "@types/http-errors": "*",
2605
+ "@types/node": "*",
2606
+ "@types/send": "<1"
2607
+ }
2608
+ },
2609
+ "node_modules/@types/serve-static/node_modules/@types/send": {
2610
+ "version": "0.17.6",
2611
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
2612
+ "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
2613
+ "license": "MIT",
2614
+ "dependencies": {
2615
+ "@types/mime": "^1",
2616
+ "@types/node": "*"
2617
+ }
2618
+ },
2619
+ "node_modules/@types/tough-cookie": {
2620
+ "version": "4.0.5",
2621
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
2622
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
2623
+ "license": "MIT",
2624
+ "optional": true
2625
+ },
2626
  "node_modules/@types/unist": {
2627
  "version": "3.0.3",
2628
  "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
 
2671
  "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
2672
  }
2673
  },
2674
+ "node_modules/abort-controller": {
2675
+ "version": "3.0.0",
2676
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
2677
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
2678
+ "license": "MIT",
2679
+ "optional": true,
2680
+ "dependencies": {
2681
+ "event-target-shim": "^5.0.0"
2682
+ },
2683
+ "engines": {
2684
+ "node": ">=6.5"
2685
+ }
2686
+ },
2687
  "node_modules/accepts": {
2688
  "version": "2.0.0",
2689
  "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
 
2745
  "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
2746
  }
2747
  },
2748
+ "node_modules/agent-base": {
2749
+ "version": "7.1.4",
2750
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
2751
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
2752
+ "license": "MIT",
2753
+ "engines": {
2754
+ "node": ">= 14"
2755
+ }
2756
+ },
2757
  "node_modules/ajv": {
2758
  "version": "6.12.6",
2759
  "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
 
2808
  "dev": true,
2809
  "license": "Python-2.0"
2810
  },
2811
+ "node_modules/arrify": {
2812
+ "version": "2.0.1",
2813
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
2814
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
2815
+ "license": "MIT",
2816
+ "optional": true,
2817
+ "engines": {
2818
+ "node": ">=8"
2819
+ }
2820
+ },
2821
+ "node_modules/async-retry": {
2822
+ "version": "1.3.3",
2823
+ "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz",
2824
+ "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==",
2825
+ "license": "MIT",
2826
+ "optional": true,
2827
+ "dependencies": {
2828
+ "retry": "0.13.1"
2829
+ }
2830
+ },
2831
  "node_modules/asynckit": {
2832
  "version": "0.4.0",
2833
  "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 
2896
  "version": "1.0.2",
2897
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
2898
  "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
2899
+ "devOptional": true,
2900
+ "license": "MIT"
2901
+ },
2902
+ "node_modules/base64-js": {
2903
+ "version": "1.5.1",
2904
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
2905
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
2906
+ "funding": [
2907
+ {
2908
+ "type": "github",
2909
+ "url": "https://github.com/sponsors/feross"
2910
+ },
2911
+ {
2912
+ "type": "patreon",
2913
+ "url": "https://www.patreon.com/feross"
2914
+ },
2915
+ {
2916
+ "type": "consulting",
2917
+ "url": "https://feross.org/support"
2918
+ }
2919
+ ],
2920
  "license": "MIT"
2921
  },
2922
  "node_modules/base64id": {
 
2952
  "node": ">= 18"
2953
  }
2954
  },
2955
+ "node_modules/bcryptjs": {
2956
+ "version": "3.0.3",
2957
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz",
2958
+ "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==",
2959
+ "license": "BSD-3-Clause",
2960
+ "bin": {
2961
+ "bcrypt": "bin/bcrypt"
2962
+ }
2963
+ },
2964
+ "node_modules/bignumber.js": {
2965
+ "version": "9.3.1",
2966
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
2967
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
2968
+ "license": "MIT",
2969
+ "engines": {
2970
+ "node": "*"
2971
+ }
2972
+ },
2973
  "node_modules/body-parser": {
2974
  "version": "2.2.1",
2975
  "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
 
3221
  "node": ">=12"
3222
  }
3223
  },
3224
+ "node_modules/cloudinary": {
3225
+ "version": "2.8.0",
3226
+ "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.8.0.tgz",
3227
+ "integrity": "sha512-s7frvR0HnQXeJsQSIsbLa/I09IMb1lOnVLEDH5b5E53WTiCYgrNNOBGV/i/nLHwrcEOUkqjfSwP1+enXWNYmdw==",
3228
+ "license": "MIT",
3229
+ "dependencies": {
3230
+ "lodash": "^4.17.21",
3231
+ "q": "^1.5.1"
3232
+ },
3233
+ "engines": {
3234
+ "node": ">=9"
3235
+ }
3236
+ },
3237
  "node_modules/color-convert": {
3238
  "version": "2.0.1",
3239
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 
3360
  "version": "7.0.6",
3361
  "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
3362
  "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
3363
+ "devOptional": true,
3364
  "license": "MIT",
3365
  "dependencies": {
3366
  "path-key": "^3.1.0",
 
3377
  "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
3378
  "license": "MIT"
3379
  },
3380
+ "node_modules/data-uri-to-buffer": {
3381
+ "version": "4.0.1",
3382
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
3383
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
3384
+ "license": "MIT",
3385
+ "optional": true,
3386
+ "peer": true,
3387
+ "engines": {
3388
+ "node": ">= 12"
3389
+ }
3390
+ },
3391
  "node_modules/debug": {
3392
  "version": "4.4.3",
3393
  "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
 
3491
  "node": ">= 0.4"
3492
  }
3493
  },
3494
+ "node_modules/duplexify": {
3495
+ "version": "4.1.3",
3496
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
3497
+ "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
3498
+ "license": "MIT",
3499
+ "optional": true,
3500
+ "dependencies": {
3501
+ "end-of-stream": "^1.4.1",
3502
+ "inherits": "^2.0.3",
3503
+ "readable-stream": "^3.1.1",
3504
+ "stream-shift": "^1.0.2"
3505
+ }
3506
+ },
3507
+ "node_modules/eastasianwidth": {
3508
+ "version": "0.2.0",
3509
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
3510
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
3511
+ "license": "MIT",
3512
+ "optional": true,
3513
+ "peer": true
3514
+ },
3515
  "node_modules/ecdsa-sig-formatter": {
3516
  "version": "1.0.11",
3517
  "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
 
3549
  "node": ">= 0.8"
3550
  }
3551
  },
3552
+ "node_modules/end-of-stream": {
3553
+ "version": "1.4.5",
3554
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
3555
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
3556
+ "license": "MIT",
3557
+ "optional": true,
3558
+ "dependencies": {
3559
+ "once": "^1.4.0"
3560
+ }
3561
+ },
3562
  "node_modules/engine.io": {
3563
  "version": "6.6.5",
3564
  "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz",
 
3941
  "node": ">= 0.6"
3942
  }
3943
  },
3944
+ "node_modules/event-target-shim": {
3945
+ "version": "5.0.1",
3946
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
3947
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
3948
+ "license": "MIT",
3949
+ "optional": true,
3950
+ "engines": {
3951
+ "node": ">=6"
3952
+ }
3953
+ },
3954
  "node_modules/express": {
3955
  "version": "5.2.1",
3956
  "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
 
4025
  "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
4026
  "license": "MIT"
4027
  },
4028
+ "node_modules/farmhash-modern": {
4029
+ "version": "1.1.0",
4030
+ "resolved": "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz",
4031
+ "integrity": "sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==",
4032
+ "license": "MIT",
4033
+ "engines": {
4034
+ "node": ">=18.0.0"
4035
+ }
4036
+ },
4037
  "node_modules/fast-deep-equal": {
4038
  "version": "3.1.3",
4039
  "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
4040
  "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
 
4041
  "license": "MIT"
4042
  },
4043
  "node_modules/fast-json-stable-stringify": {
 
4054
  "dev": true,
4055
  "license": "MIT"
4056
  },
4057
+ "node_modules/fast-xml-parser": {
4058
+ "version": "4.5.3",
4059
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
4060
+ "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
4061
+ "funding": [
4062
+ {
4063
+ "type": "github",
4064
+ "url": "https://github.com/sponsors/NaturalIntelligence"
4065
+ }
4066
+ ],
4067
+ "license": "MIT",
4068
+ "optional": true,
4069
+ "dependencies": {
4070
+ "strnum": "^1.1.1"
4071
+ },
4072
+ "bin": {
4073
+ "fxparser": "src/cli/cli.js"
4074
+ }
4075
+ },
4076
  "node_modules/faye-websocket": {
4077
  "version": "0.11.4",
4078
  "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
 
4103
  }
4104
  }
4105
  },
4106
+ "node_modules/fetch-blob": {
4107
+ "version": "3.2.0",
4108
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
4109
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
4110
+ "funding": [
4111
+ {
4112
+ "type": "github",
4113
+ "url": "https://github.com/sponsors/jimmywarting"
4114
+ },
4115
+ {
4116
+ "type": "paypal",
4117
+ "url": "https://paypal.me/jimmywarting"
4118
+ }
4119
+ ],
4120
+ "license": "MIT",
4121
+ "optional": true,
4122
+ "peer": true,
4123
+ "dependencies": {
4124
+ "node-domexception": "^1.0.0",
4125
+ "web-streams-polyfill": "^3.0.3"
4126
+ },
4127
+ "engines": {
4128
+ "node": "^12.20 || >= 14.13"
4129
+ }
4130
+ },
4131
  "node_modules/file-entry-cache": {
4132
  "version": "8.0.0",
4133
  "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
 
4215
  "@firebase/util": "1.13.0"
4216
  }
4217
  },
4218
+ "node_modules/firebase-admin": {
4219
+ "version": "13.6.0",
4220
+ "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.6.0.tgz",
4221
+ "integrity": "sha512-GdPA/t0+Cq8p1JnjFRBmxRxAGvF/kl2yfdhALl38PrRp325YxyQ5aNaHui0XmaKcKiGRFIJ/EgBNWFoDP0onjw==",
4222
+ "license": "Apache-2.0",
4223
+ "dependencies": {
4224
+ "@fastify/busboy": "^3.0.0",
4225
+ "@firebase/database-compat": "^2.0.0",
4226
+ "@firebase/database-types": "^1.0.6",
4227
+ "@types/node": "^22.8.7",
4228
+ "farmhash-modern": "^1.1.0",
4229
+ "fast-deep-equal": "^3.1.1",
4230
+ "google-auth-library": "^9.14.2",
4231
+ "jsonwebtoken": "^9.0.0",
4232
+ "jwks-rsa": "^3.1.0",
4233
+ "node-forge": "^1.3.1",
4234
+ "uuid": "^11.0.2"
4235
+ },
4236
+ "engines": {
4237
+ "node": ">=18"
4238
+ },
4239
+ "optionalDependencies": {
4240
+ "@google-cloud/firestore": "^7.11.0",
4241
+ "@google-cloud/storage": "^7.14.0"
4242
+ }
4243
+ },
4244
+ "node_modules/firebase-admin/node_modules/@types/node": {
4245
+ "version": "22.19.3",
4246
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz",
4247
+ "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==",
4248
+ "license": "MIT",
4249
+ "dependencies": {
4250
+ "undici-types": "~6.21.0"
4251
+ }
4252
+ },
4253
+ "node_modules/firebase-admin/node_modules/undici-types": {
4254
+ "version": "6.21.0",
4255
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
4256
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
4257
+ "license": "MIT"
4258
+ },
4259
  "node_modules/flat-cache": {
4260
  "version": "4.0.1",
4261
  "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
 
4297
  }
4298
  }
4299
  },
4300
+ "node_modules/foreground-child": {
4301
+ "version": "3.3.1",
4302
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
4303
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
4304
+ "license": "ISC",
4305
+ "optional": true,
4306
+ "peer": true,
4307
+ "dependencies": {
4308
+ "cross-spawn": "^7.0.6",
4309
+ "signal-exit": "^4.0.1"
4310
+ },
4311
+ "engines": {
4312
+ "node": ">=14"
4313
+ },
4314
+ "funding": {
4315
+ "url": "https://github.com/sponsors/isaacs"
4316
+ }
4317
+ },
4318
  "node_modules/form-data": {
4319
  "version": "4.0.5",
4320
  "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
 
4331
  "node": ">= 6"
4332
  }
4333
  },
4334
+ "node_modules/formdata-polyfill": {
4335
+ "version": "4.0.10",
4336
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
4337
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
4338
+ "license": "MIT",
4339
+ "optional": true,
4340
+ "peer": true,
4341
+ "dependencies": {
4342
+ "fetch-blob": "^3.1.2"
4343
+ },
4344
+ "engines": {
4345
+ "node": ">=12.20.0"
4346
+ }
4347
+ },
4348
  "node_modules/forwarded": {
4349
  "version": "0.2.0",
4350
  "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
 
4401
  "url": "https://github.com/sponsors/ljharb"
4402
  }
4403
  },
4404
+ "node_modules/functional-red-black-tree": {
4405
+ "version": "1.0.1",
4406
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
4407
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
4408
+ "license": "MIT",
4409
+ "optional": true
4410
+ },
4411
+ "node_modules/gaxios": {
4412
+ "version": "6.7.1",
4413
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
4414
+ "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
4415
+ "license": "Apache-2.0",
4416
+ "dependencies": {
4417
+ "extend": "^3.0.2",
4418
+ "https-proxy-agent": "^7.0.1",
4419
+ "is-stream": "^2.0.0",
4420
+ "node-fetch": "^2.6.9",
4421
+ "uuid": "^9.0.1"
4422
+ },
4423
+ "engines": {
4424
+ "node": ">=14"
4425
+ }
4426
+ },
4427
+ "node_modules/gaxios/node_modules/uuid": {
4428
+ "version": "9.0.1",
4429
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
4430
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
4431
+ "funding": [
4432
+ "https://github.com/sponsors/broofa",
4433
+ "https://github.com/sponsors/ctavan"
4434
+ ],
4435
+ "license": "MIT",
4436
+ "bin": {
4437
+ "uuid": "dist/bin/uuid"
4438
+ }
4439
+ },
4440
+ "node_modules/gcp-metadata": {
4441
+ "version": "7.0.1",
4442
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.1.tgz",
4443
+ "integrity": "sha512-UcO3kefx6dCcZkgcTGgVOTFb7b1LlQ02hY1omMjjrrBzkajRMCFgYOjs7J71WqnuG1k2b+9ppGL7FsOfhZMQKQ==",
4444
+ "license": "Apache-2.0",
4445
+ "optional": true,
4446
+ "peer": true,
4447
+ "dependencies": {
4448
+ "gaxios": "^7.0.0",
4449
+ "google-logging-utils": "^1.0.0",
4450
+ "json-bigint": "^1.0.0"
4451
+ },
4452
+ "engines": {
4453
+ "node": ">=18"
4454
+ }
4455
+ },
4456
+ "node_modules/gcp-metadata/node_modules/gaxios": {
4457
+ "version": "7.1.3",
4458
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz",
4459
+ "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==",
4460
+ "license": "Apache-2.0",
4461
+ "optional": true,
4462
+ "peer": true,
4463
+ "dependencies": {
4464
+ "extend": "^3.0.2",
4465
+ "https-proxy-agent": "^7.0.1",
4466
+ "node-fetch": "^3.3.2",
4467
+ "rimraf": "^5.0.1"
4468
+ },
4469
+ "engines": {
4470
+ "node": ">=18"
4471
+ }
4472
+ },
4473
+ "node_modules/gcp-metadata/node_modules/node-fetch": {
4474
+ "version": "3.3.2",
4475
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
4476
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
4477
+ "license": "MIT",
4478
+ "optional": true,
4479
+ "peer": true,
4480
+ "dependencies": {
4481
+ "data-uri-to-buffer": "^4.0.0",
4482
+ "fetch-blob": "^3.1.4",
4483
+ "formdata-polyfill": "^4.0.10"
4484
+ },
4485
+ "engines": {
4486
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
4487
+ },
4488
+ "funding": {
4489
+ "type": "opencollective",
4490
+ "url": "https://opencollective.com/node-fetch"
4491
+ }
4492
+ },
4493
  "node_modules/gensync": {
4494
  "version": "1.0.0-beta.2",
4495
  "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
 
4546
  "node": ">= 0.4"
4547
  }
4548
  },
4549
+ "node_modules/glob": {
4550
+ "version": "10.5.0",
4551
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
4552
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
4553
+ "license": "ISC",
4554
+ "optional": true,
4555
+ "peer": true,
4556
+ "dependencies": {
4557
+ "foreground-child": "^3.1.0",
4558
+ "jackspeak": "^3.1.2",
4559
+ "minimatch": "^9.0.4",
4560
+ "minipass": "^7.1.2",
4561
+ "package-json-from-dist": "^1.0.0",
4562
+ "path-scurry": "^1.11.1"
4563
+ },
4564
+ "bin": {
4565
+ "glob": "dist/esm/bin.mjs"
4566
+ },
4567
+ "funding": {
4568
+ "url": "https://github.com/sponsors/isaacs"
4569
+ }
4570
+ },
4571
  "node_modules/glob-parent": {
4572
  "version": "6.0.2",
4573
  "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
 
4581
  "node": ">=10.13.0"
4582
  }
4583
  },
4584
+ "node_modules/glob/node_modules/brace-expansion": {
4585
+ "version": "2.0.2",
4586
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
4587
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
4588
+ "license": "MIT",
4589
+ "optional": true,
4590
+ "peer": true,
4591
+ "dependencies": {
4592
+ "balanced-match": "^1.0.0"
4593
+ }
4594
+ },
4595
+ "node_modules/glob/node_modules/minimatch": {
4596
+ "version": "9.0.5",
4597
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
4598
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
4599
+ "license": "ISC",
4600
+ "optional": true,
4601
+ "peer": true,
4602
+ "dependencies": {
4603
+ "brace-expansion": "^2.0.1"
4604
+ },
4605
+ "engines": {
4606
+ "node": ">=16 || 14 >=14.17"
4607
+ },
4608
+ "funding": {
4609
+ "url": "https://github.com/sponsors/isaacs"
4610
+ }
4611
+ },
4612
  "node_modules/globals": {
4613
  "version": "16.5.0",
4614
  "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
 
4622
  "url": "https://github.com/sponsors/sindresorhus"
4623
  }
4624
  },
4625
+ "node_modules/google-auth-library": {
4626
+ "version": "9.15.1",
4627
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz",
4628
+ "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==",
4629
+ "license": "Apache-2.0",
4630
+ "dependencies": {
4631
+ "base64-js": "^1.3.0",
4632
+ "ecdsa-sig-formatter": "^1.0.11",
4633
+ "gaxios": "^6.1.1",
4634
+ "gcp-metadata": "^6.1.0",
4635
+ "gtoken": "^7.0.0",
4636
+ "jws": "^4.0.0"
4637
+ },
4638
+ "engines": {
4639
+ "node": ">=14"
4640
+ }
4641
+ },
4642
+ "node_modules/google-auth-library/node_modules/gcp-metadata": {
4643
+ "version": "6.1.1",
4644
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
4645
+ "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==",
4646
+ "license": "Apache-2.0",
4647
+ "dependencies": {
4648
+ "gaxios": "^6.1.1",
4649
+ "google-logging-utils": "^0.0.2",
4650
+ "json-bigint": "^1.0.0"
4651
+ },
4652
+ "engines": {
4653
+ "node": ">=14"
4654
+ }
4655
+ },
4656
+ "node_modules/google-auth-library/node_modules/google-logging-utils": {
4657
+ "version": "0.0.2",
4658
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
4659
+ "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==",
4660
+ "license": "Apache-2.0",
4661
+ "engines": {
4662
+ "node": ">=14"
4663
+ }
4664
+ },
4665
+ "node_modules/google-gax": {
4666
+ "version": "4.6.1",
4667
+ "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.6.1.tgz",
4668
+ "integrity": "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==",
4669
+ "license": "Apache-2.0",
4670
+ "optional": true,
4671
+ "dependencies": {
4672
+ "@grpc/grpc-js": "^1.10.9",
4673
+ "@grpc/proto-loader": "^0.7.13",
4674
+ "@types/long": "^4.0.0",
4675
+ "abort-controller": "^3.0.0",
4676
+ "duplexify": "^4.0.0",
4677
+ "google-auth-library": "^9.3.0",
4678
+ "node-fetch": "^2.7.0",
4679
+ "object-hash": "^3.0.0",
4680
+ "proto3-json-serializer": "^2.0.2",
4681
+ "protobufjs": "^7.3.2",
4682
+ "retry-request": "^7.0.0",
4683
+ "uuid": "^9.0.1"
4684
+ },
4685
+ "engines": {
4686
+ "node": ">=14"
4687
+ }
4688
+ },
4689
+ "node_modules/google-gax/node_modules/@grpc/grpc-js": {
4690
+ "version": "1.14.3",
4691
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz",
4692
+ "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==",
4693
+ "license": "Apache-2.0",
4694
+ "optional": true,
4695
+ "dependencies": {
4696
+ "@grpc/proto-loader": "^0.8.0",
4697
+ "@js-sdsl/ordered-map": "^4.4.2"
4698
+ },
4699
+ "engines": {
4700
+ "node": ">=12.10.0"
4701
+ }
4702
+ },
4703
+ "node_modules/google-gax/node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": {
4704
+ "version": "0.8.0",
4705
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz",
4706
+ "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==",
4707
+ "license": "Apache-2.0",
4708
+ "optional": true,
4709
+ "dependencies": {
4710
+ "lodash.camelcase": "^4.3.0",
4711
+ "long": "^5.0.0",
4712
+ "protobufjs": "^7.5.3",
4713
+ "yargs": "^17.7.2"
4714
+ },
4715
+ "bin": {
4716
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
4717
+ },
4718
+ "engines": {
4719
+ "node": ">=6"
4720
+ }
4721
+ },
4722
+ "node_modules/google-gax/node_modules/uuid": {
4723
+ "version": "9.0.1",
4724
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
4725
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
4726
+ "funding": [
4727
+ "https://github.com/sponsors/broofa",
4728
+ "https://github.com/sponsors/ctavan"
4729
+ ],
4730
+ "license": "MIT",
4731
+ "optional": true,
4732
+ "bin": {
4733
+ "uuid": "dist/bin/uuid"
4734
+ }
4735
+ },
4736
+ "node_modules/google-logging-utils": {
4737
+ "version": "1.1.3",
4738
+ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz",
4739
+ "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==",
4740
+ "license": "Apache-2.0",
4741
+ "optional": true,
4742
+ "peer": true,
4743
+ "engines": {
4744
+ "node": ">=14"
4745
+ }
4746
+ },
4747
  "node_modules/gopd": {
4748
  "version": "1.2.0",
4749
  "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
 
4756
  "url": "https://github.com/sponsors/ljharb"
4757
  }
4758
  },
4759
+ "node_modules/gtoken": {
4760
+ "version": "7.1.0",
4761
+ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz",
4762
+ "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==",
4763
+ "license": "MIT",
4764
+ "dependencies": {
4765
+ "gaxios": "^6.0.0",
4766
+ "jws": "^4.0.0"
4767
+ },
4768
+ "engines": {
4769
+ "node": ">=14.0.0"
4770
+ }
4771
+ },
4772
  "node_modules/has-flag": {
4773
  "version": "4.0.0",
4774
  "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
 
4875
  "hermes-estree": "0.25.1"
4876
  }
4877
  },
4878
+ "node_modules/html-entities": {
4879
+ "version": "2.6.0",
4880
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
4881
+ "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
4882
+ "funding": [
4883
+ {
4884
+ "type": "github",
4885
+ "url": "https://github.com/sponsors/mdevils"
4886
+ },
4887
+ {
4888
+ "type": "patreon",
4889
+ "url": "https://patreon.com/mdevils"
4890
+ }
4891
+ ],
4892
+ "license": "MIT",
4893
+ "optional": true
4894
+ },
4895
  "node_modules/html-url-attributes": {
4896
  "version": "3.0.1",
4897
  "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
 
4928
  "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
4929
  "license": "MIT"
4930
  },
4931
+ "node_modules/http-proxy-agent": {
4932
+ "version": "5.0.0",
4933
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
4934
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
4935
+ "license": "MIT",
4936
+ "optional": true,
4937
+ "dependencies": {
4938
+ "@tootallnate/once": "2",
4939
+ "agent-base": "6",
4940
+ "debug": "4"
4941
+ },
4942
+ "engines": {
4943
+ "node": ">= 6"
4944
+ }
4945
+ },
4946
+ "node_modules/http-proxy-agent/node_modules/agent-base": {
4947
+ "version": "6.0.2",
4948
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
4949
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
4950
+ "license": "MIT",
4951
+ "optional": true,
4952
+ "dependencies": {
4953
+ "debug": "4"
4954
+ },
4955
+ "engines": {
4956
+ "node": ">= 6.0.0"
4957
+ }
4958
+ },
4959
+ "node_modules/https-proxy-agent": {
4960
+ "version": "7.0.6",
4961
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
4962
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
4963
+ "license": "MIT",
4964
+ "dependencies": {
4965
+ "agent-base": "^7.1.2",
4966
+ "debug": "4"
4967
+ },
4968
+ "engines": {
4969
+ "node": ">= 14"
4970
+ }
4971
+ },
4972
  "node_modules/iconv-lite": {
4973
  "version": "0.7.1",
4974
  "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
 
5143
  "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
5144
  "license": "MIT"
5145
  },
5146
+ "node_modules/is-stream": {
5147
+ "version": "2.0.1",
5148
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
5149
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
5150
+ "license": "MIT",
5151
+ "engines": {
5152
+ "node": ">=8"
5153
+ },
5154
+ "funding": {
5155
+ "url": "https://github.com/sponsors/sindresorhus"
5156
+ }
5157
+ },
5158
  "node_modules/isexe": {
5159
  "version": "2.0.0",
5160
  "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
5161
  "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
5162
+ "devOptional": true,
5163
  "license": "ISC"
5164
  },
5165
+ "node_modules/jackspeak": {
5166
+ "version": "3.4.3",
5167
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
5168
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
5169
+ "license": "BlueOak-1.0.0",
5170
+ "optional": true,
5171
+ "peer": true,
5172
+ "dependencies": {
5173
+ "@isaacs/cliui": "^8.0.2"
5174
+ },
5175
+ "funding": {
5176
+ "url": "https://github.com/sponsors/isaacs"
5177
+ },
5178
+ "optionalDependencies": {
5179
+ "@pkgjs/parseargs": "^0.11.0"
5180
+ }
5181
+ },
5182
+ "node_modules/jose": {
5183
+ "version": "4.15.9",
5184
+ "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
5185
+ "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
5186
+ "license": "MIT",
5187
+ "funding": {
5188
+ "url": "https://github.com/sponsors/panva"
5189
+ }
5190
+ },
5191
  "node_modules/js-tokens": {
5192
  "version": "4.0.0",
5193
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
 
5221
  "node": ">=6"
5222
  }
5223
  },
5224
+ "node_modules/json-bigint": {
5225
+ "version": "1.0.0",
5226
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
5227
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
5228
+ "license": "MIT",
5229
+ "dependencies": {
5230
+ "bignumber.js": "^9.0.0"
5231
+ }
5232
+ },
5233
  "node_modules/json-buffer": {
5234
  "version": "3.0.1",
5235
  "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
 
5309
  "safe-buffer": "^5.0.1"
5310
  }
5311
  },
5312
+ "node_modules/jwks-rsa": {
5313
+ "version": "3.2.0",
5314
+ "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.0.tgz",
5315
+ "integrity": "sha512-PwchfHcQK/5PSydeKCs1ylNym0w/SSv8a62DgHJ//7x2ZclCoinlsjAfDxAAbpoTPybOum/Jgy+vkvMmKz89Ww==",
5316
+ "license": "MIT",
5317
+ "dependencies": {
5318
+ "@types/express": "^4.17.20",
5319
+ "@types/jsonwebtoken": "^9.0.4",
5320
+ "debug": "^4.3.4",
5321
+ "jose": "^4.15.4",
5322
+ "limiter": "^1.1.5",
5323
+ "lru-memoizer": "^2.2.0"
5324
+ },
5325
+ "engines": {
5326
+ "node": ">=14"
5327
+ }
5328
+ },
5329
  "node_modules/jws": {
5330
  "version": "4.0.1",
5331
  "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
 
5375
  "node": ">= 0.8.0"
5376
  }
5377
  },
5378
+ "node_modules/limiter": {
5379
+ "version": "1.1.5",
5380
+ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
5381
+ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
5382
+ },
5383
  "node_modules/locate-path": {
5384
  "version": "6.0.0",
5385
  "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
 
5396
  "url": "https://github.com/sponsors/sindresorhus"
5397
  }
5398
  },
5399
+ "node_modules/lodash": {
5400
+ "version": "4.17.21",
5401
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
5402
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
5403
+ "license": "MIT"
5404
+ },
5405
  "node_modules/lodash.camelcase": {
5406
  "version": "4.3.0",
5407
  "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
5408
  "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
5409
  "license": "MIT"
5410
  },
5411
+ "node_modules/lodash.clonedeep": {
5412
+ "version": "4.5.0",
5413
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
5414
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
5415
+ "license": "MIT"
5416
+ },
5417
  "node_modules/lodash.includes": {
5418
  "version": "4.3.0",
5419
  "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
 
5489
  "yallist": "^3.0.2"
5490
  }
5491
  },
5492
+ "node_modules/lru-memoizer": {
5493
+ "version": "2.3.0",
5494
+ "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz",
5495
+ "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==",
5496
+ "license": "MIT",
5497
+ "dependencies": {
5498
+ "lodash.clonedeep": "^4.5.0",
5499
+ "lru-cache": "6.0.0"
5500
+ }
5501
+ },
5502
+ "node_modules/lru-memoizer/node_modules/lru-cache": {
5503
+ "version": "6.0.0",
5504
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
5505
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
5506
+ "license": "ISC",
5507
+ "dependencies": {
5508
+ "yallist": "^4.0.0"
5509
+ },
5510
+ "engines": {
5511
+ "node": ">=10"
5512
+ }
5513
+ },
5514
+ "node_modules/lru-memoizer/node_modules/yallist": {
5515
+ "version": "4.0.0",
5516
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
5517
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
5518
+ "license": "ISC"
5519
+ },
5520
  "node_modules/lucide-react": {
5521
  "version": "0.562.0",
5522
  "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz",
 
6157
  ],
6158
  "license": "MIT"
6159
  },
6160
+ "node_modules/mime": {
6161
+ "version": "3.0.0",
6162
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
6163
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
6164
+ "license": "MIT",
6165
+ "optional": true,
6166
+ "bin": {
6167
+ "mime": "cli.js"
6168
+ },
6169
+ "engines": {
6170
+ "node": ">=10.0.0"
6171
+ }
6172
+ },
6173
  "node_modules/mime-db": {
6174
  "version": "1.52.0",
6175
  "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
 
6213
  "url": "https://github.com/sponsors/ljharb"
6214
  }
6215
  },
6216
+ "node_modules/minipass": {
6217
+ "version": "7.1.2",
6218
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
6219
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
6220
+ "license": "ISC",
6221
+ "optional": true,
6222
+ "peer": true,
6223
+ "engines": {
6224
+ "node": ">=16 || 14 >=14.17"
6225
+ }
6226
+ },
6227
  "node_modules/mkdirp": {
6228
  "version": "0.5.6",
6229
  "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
 
6296
  }
6297
  },
6298
  "node_modules/mongoose": {
6299
+ "version": "9.1.1",
6300
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.1.1.tgz",
6301
+ "integrity": "sha512-/CgKSAmjzgIj4o1FyWZIpQ2rmUQlhalwWd4l/Ht3XUVWscHRHev1TIwKz1ADNC5tHHyOQEaUDkEh0jI91c4Ydw==",
6302
  "license": "MIT",
6303
  "dependencies": {
6304
  "kareem": "3.0.0",
 
6424
  "node": "^18 || ^20 || >= 21"
6425
  }
6426
  },
6427
+ "node_modules/node-domexception": {
6428
+ "version": "1.0.0",
6429
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
6430
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
6431
+ "deprecated": "Use your platform's native DOMException instead",
6432
+ "funding": [
6433
+ {
6434
+ "type": "github",
6435
+ "url": "https://github.com/sponsors/jimmywarting"
6436
+ },
6437
+ {
6438
+ "type": "github",
6439
+ "url": "https://paypal.me/jimmywarting"
6440
+ }
6441
+ ],
6442
+ "license": "MIT",
6443
+ "optional": true,
6444
+ "peer": true,
6445
+ "engines": {
6446
+ "node": ">=10.5.0"
6447
+ }
6448
+ },
6449
+ "node_modules/node-fetch": {
6450
+ "version": "2.7.0",
6451
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
6452
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
6453
+ "license": "MIT",
6454
+ "dependencies": {
6455
+ "whatwg-url": "^5.0.0"
6456
+ },
6457
+ "engines": {
6458
+ "node": "4.x || >=6.0.0"
6459
+ },
6460
+ "peerDependencies": {
6461
+ "encoding": "^0.1.0"
6462
+ },
6463
+ "peerDependenciesMeta": {
6464
+ "encoding": {
6465
+ "optional": true
6466
+ }
6467
+ }
6468
+ },
6469
+ "node_modules/node-fetch/node_modules/tr46": {
6470
+ "version": "0.0.3",
6471
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
6472
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
6473
+ "license": "MIT"
6474
+ },
6475
+ "node_modules/node-fetch/node_modules/webidl-conversions": {
6476
+ "version": "3.0.1",
6477
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
6478
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
6479
+ "license": "BSD-2-Clause"
6480
+ },
6481
+ "node_modules/node-fetch/node_modules/whatwg-url": {
6482
+ "version": "5.0.0",
6483
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
6484
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
6485
+ "license": "MIT",
6486
+ "dependencies": {
6487
+ "tr46": "~0.0.3",
6488
+ "webidl-conversions": "^3.0.0"
6489
+ }
6490
+ },
6491
+ "node_modules/node-forge": {
6492
+ "version": "1.3.3",
6493
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz",
6494
+ "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==",
6495
+ "license": "(BSD-3-Clause OR GPL-2.0)",
6496
+ "engines": {
6497
+ "node": ">= 6.13.0"
6498
+ }
6499
+ },
6500
  "node_modules/node-gyp-build": {
6501
  "version": "4.8.4",
6502
  "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
 
6515
  "dev": true,
6516
  "license": "MIT"
6517
  },
6518
+ "node_modules/nodemailer": {
6519
+ "version": "7.0.12",
6520
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.12.tgz",
6521
+ "integrity": "sha512-H+rnK5bX2Pi/6ms3sN4/jRQvYSMltV6vqup/0SFOrxYYY/qoNvhXPlYq3e+Pm9RFJRwrMGbMIwi81M4dxpomhA==",
6522
+ "license": "MIT-0",
6523
+ "engines": {
6524
+ "node": ">=6.0.0"
6525
+ }
6526
+ },
6527
  "node_modules/object-assign": {
6528
  "version": "4.1.1",
6529
  "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
 
6533
  "node": ">=0.10.0"
6534
  }
6535
  },
6536
+ "node_modules/object-hash": {
6537
+ "version": "3.0.0",
6538
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
6539
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
6540
+ "license": "MIT",
6541
+ "optional": true,
6542
+ "engines": {
6543
+ "node": ">= 6"
6544
+ }
6545
+ },
6546
  "node_modules/object-inspect": {
6547
  "version": "1.13.4",
6548
  "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
 
6598
  "version": "3.1.0",
6599
  "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
6600
  "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
6601
+ "devOptional": true,
6602
  "license": "MIT",
6603
  "dependencies": {
6604
  "yocto-queue": "^0.1.0"
 
6626
  "url": "https://github.com/sponsors/sindresorhus"
6627
  }
6628
  },
6629
+ "node_modules/package-json-from-dist": {
6630
+ "version": "1.0.1",
6631
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
6632
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
6633
+ "license": "BlueOak-1.0.0",
6634
+ "optional": true,
6635
+ "peer": true
6636
+ },
6637
  "node_modules/parent-module": {
6638
  "version": "1.0.1",
6639
  "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
 
6695
  "version": "3.1.1",
6696
  "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
6697
  "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
6698
+ "devOptional": true,
6699
  "license": "MIT",
6700
  "engines": {
6701
  "node": ">=8"
6702
  }
6703
  },
6704
+ "node_modules/path-scurry": {
6705
+ "version": "1.11.1",
6706
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
6707
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
6708
+ "license": "BlueOak-1.0.0",
6709
+ "optional": true,
6710
+ "peer": true,
6711
+ "dependencies": {
6712
+ "lru-cache": "^10.2.0",
6713
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
6714
+ },
6715
+ "engines": {
6716
+ "node": ">=16 || 14 >=14.18"
6717
+ },
6718
+ "funding": {
6719
+ "url": "https://github.com/sponsors/isaacs"
6720
+ }
6721
+ },
6722
+ "node_modules/path-scurry/node_modules/lru-cache": {
6723
+ "version": "10.4.3",
6724
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
6725
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
6726
+ "license": "ISC",
6727
+ "optional": true,
6728
+ "peer": true
6729
+ },
6730
  "node_modules/path-to-regexp": {
6731
  "version": "8.3.0",
6732
  "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
 
6813
  "url": "https://github.com/sponsors/wooorm"
6814
  }
6815
  },
6816
+ "node_modules/proto3-json-serializer": {
6817
+ "version": "2.0.2",
6818
+ "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz",
6819
+ "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==",
6820
+ "license": "Apache-2.0",
6821
+ "optional": true,
6822
+ "dependencies": {
6823
+ "protobufjs": "^7.2.5"
6824
+ },
6825
+ "engines": {
6826
+ "node": ">=14.0.0"
6827
+ }
6828
+ },
6829
  "node_modules/protobufjs": {
6830
  "version": "7.5.4",
6831
  "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz",
 
6878
  "node": ">=6"
6879
  }
6880
  },
6881
+ "node_modules/q": {
6882
+ "version": "1.5.1",
6883
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
6884
+ "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
6885
+ "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)",
6886
+ "license": "MIT",
6887
+ "engines": {
6888
+ "node": ">=0.6.0",
6889
+ "teleport": ">=0.2.0"
6890
+ }
6891
+ },
6892
  "node_modules/qs": {
6893
  "version": "6.14.1",
6894
  "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
 
7066
  "node": ">=4"
7067
  }
7068
  },
7069
+ "node_modules/retry": {
7070
+ "version": "0.13.1",
7071
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
7072
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
7073
+ "license": "MIT",
7074
+ "optional": true,
7075
+ "engines": {
7076
+ "node": ">= 4"
7077
+ }
7078
+ },
7079
+ "node_modules/retry-request": {
7080
+ "version": "7.0.2",
7081
+ "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz",
7082
+ "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==",
7083
+ "license": "MIT",
7084
+ "optional": true,
7085
+ "dependencies": {
7086
+ "@types/request": "^2.48.8",
7087
+ "extend": "^3.0.2",
7088
+ "teeny-request": "^9.0.0"
7089
+ },
7090
+ "engines": {
7091
+ "node": ">=14"
7092
+ }
7093
+ },
7094
+ "node_modules/rimraf": {
7095
+ "version": "5.0.10",
7096
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
7097
+ "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==",
7098
+ "license": "ISC",
7099
+ "optional": true,
7100
+ "peer": true,
7101
+ "dependencies": {
7102
+ "glob": "^10.3.7"
7103
+ },
7104
+ "bin": {
7105
+ "rimraf": "dist/esm/bin.mjs"
7106
+ },
7107
+ "funding": {
7108
+ "url": "https://github.com/sponsors/isaacs"
7109
+ }
7110
+ },
7111
  "node_modules/rollup": {
7112
  "version": "4.54.0",
7113
  "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz",
 
7288
  "version": "2.0.0",
7289
  "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
7290
  "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
7291
+ "devOptional": true,
7292
  "license": "MIT",
7293
  "dependencies": {
7294
  "shebang-regex": "^3.0.0"
 
7301
  "version": "3.0.0",
7302
  "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
7303
  "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
7304
+ "devOptional": true,
7305
  "license": "MIT",
7306
  "engines": {
7307
  "node": ">=8"
 
7385
  "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==",
7386
  "license": "MIT"
7387
  },
7388
+ "node_modules/signal-exit": {
7389
+ "version": "4.1.0",
7390
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
7391
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
7392
+ "license": "ISC",
7393
+ "optional": true,
7394
+ "peer": true,
7395
+ "engines": {
7396
+ "node": ">=14"
7397
+ },
7398
+ "funding": {
7399
+ "url": "https://github.com/sponsors/isaacs"
7400
+ }
7401
+ },
7402
  "node_modules/socket.io": {
7403
  "version": "4.8.3",
7404
  "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz",
 
7515
  "node": ">= 0.8"
7516
  }
7517
  },
7518
+ "node_modules/stream-events": {
7519
+ "version": "1.0.5",
7520
+ "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
7521
+ "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
7522
+ "license": "MIT",
7523
+ "optional": true,
7524
+ "dependencies": {
7525
+ "stubs": "^3.0.0"
7526
+ }
7527
+ },
7528
+ "node_modules/stream-shift": {
7529
+ "version": "1.0.3",
7530
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
7531
+ "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
7532
+ "license": "MIT",
7533
+ "optional": true
7534
+ },
7535
  "node_modules/streamsearch": {
7536
  "version": "1.1.0",
7537
  "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
 
7563
  "node": ">=8"
7564
  }
7565
  },
7566
+ "node_modules/string-width-cjs": {
7567
+ "name": "string-width",
7568
+ "version": "4.2.3",
7569
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
7570
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
7571
+ "license": "MIT",
7572
+ "optional": true,
7573
+ "peer": true,
7574
+ "dependencies": {
7575
+ "emoji-regex": "^8.0.0",
7576
+ "is-fullwidth-code-point": "^3.0.0",
7577
+ "strip-ansi": "^6.0.1"
7578
+ },
7579
+ "engines": {
7580
+ "node": ">=8"
7581
+ }
7582
+ },
7583
  "node_modules/stringify-entities": {
7584
  "version": "4.0.4",
7585
  "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
 
7606
  "node": ">=8"
7607
  }
7608
  },
7609
+ "node_modules/strip-ansi-cjs": {
7610
+ "name": "strip-ansi",
7611
+ "version": "6.0.1",
7612
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
7613
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
7614
+ "license": "MIT",
7615
+ "optional": true,
7616
+ "peer": true,
7617
+ "dependencies": {
7618
+ "ansi-regex": "^5.0.1"
7619
+ },
7620
+ "engines": {
7621
+ "node": ">=8"
7622
+ }
7623
+ },
7624
  "node_modules/strip-json-comments": {
7625
  "version": "3.1.1",
7626
  "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
 
7634
  "url": "https://github.com/sponsors/sindresorhus"
7635
  }
7636
  },
7637
+ "node_modules/strnum": {
7638
+ "version": "1.1.2",
7639
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
7640
+ "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
7641
+ "funding": [
7642
+ {
7643
+ "type": "github",
7644
+ "url": "https://github.com/sponsors/NaturalIntelligence"
7645
+ }
7646
+ ],
7647
+ "license": "MIT",
7648
+ "optional": true
7649
+ },
7650
+ "node_modules/stubs": {
7651
+ "version": "3.0.0",
7652
+ "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
7653
+ "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==",
7654
+ "license": "MIT",
7655
+ "optional": true
7656
+ },
7657
  "node_modules/style-to-js": {
7658
  "version": "1.1.21",
7659
  "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
 
7692
  "dev": true,
7693
  "license": "MIT"
7694
  },
7695
+ "node_modules/teeny-request": {
7696
+ "version": "9.0.0",
7697
+ "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz",
7698
+ "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==",
7699
+ "license": "Apache-2.0",
7700
+ "optional": true,
7701
+ "dependencies": {
7702
+ "http-proxy-agent": "^5.0.0",
7703
+ "https-proxy-agent": "^5.0.0",
7704
+ "node-fetch": "^2.6.9",
7705
+ "stream-events": "^1.0.5",
7706
+ "uuid": "^9.0.0"
7707
+ },
7708
+ "engines": {
7709
+ "node": ">=14"
7710
+ }
7711
+ },
7712
+ "node_modules/teeny-request/node_modules/agent-base": {
7713
+ "version": "6.0.2",
7714
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
7715
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
7716
+ "license": "MIT",
7717
+ "optional": true,
7718
+ "dependencies": {
7719
+ "debug": "4"
7720
+ },
7721
+ "engines": {
7722
+ "node": ">= 6.0.0"
7723
+ }
7724
+ },
7725
+ "node_modules/teeny-request/node_modules/https-proxy-agent": {
7726
+ "version": "5.0.1",
7727
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
7728
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
7729
+ "license": "MIT",
7730
+ "optional": true,
7731
+ "dependencies": {
7732
+ "agent-base": "6",
7733
+ "debug": "4"
7734
+ },
7735
+ "engines": {
7736
+ "node": ">= 6"
7737
+ }
7738
+ },
7739
+ "node_modules/teeny-request/node_modules/uuid": {
7740
+ "version": "9.0.1",
7741
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
7742
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
7743
+ "funding": [
7744
+ "https://github.com/sponsors/broofa",
7745
+ "https://github.com/sponsors/ctavan"
7746
+ ],
7747
+ "license": "MIT",
7748
+ "optional": true,
7749
+ "bin": {
7750
+ "uuid": "dist/bin/uuid"
7751
+ }
7752
+ },
7753
  "node_modules/tinyglobby": {
7754
  "version": "0.2.15",
7755
  "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
 
8021
  "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
8022
  "license": "MIT"
8023
  },
8024
+ "node_modules/uuid": {
8025
+ "version": "11.1.0",
8026
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
8027
+ "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
8028
+ "funding": [
8029
+ "https://github.com/sponsors/broofa",
8030
+ "https://github.com/sponsors/ctavan"
8031
+ ],
8032
+ "license": "MIT",
8033
+ "bin": {
8034
+ "uuid": "dist/esm/bin/uuid"
8035
+ }
8036
+ },
8037
  "node_modules/vary": {
8038
  "version": "1.1.2",
8039
  "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
 
8146
  }
8147
  }
8148
  },
8149
+ "node_modules/web-streams-polyfill": {
8150
+ "version": "3.3.3",
8151
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
8152
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
8153
+ "license": "MIT",
8154
+ "optional": true,
8155
+ "peer": true,
8156
+ "engines": {
8157
+ "node": ">= 8"
8158
+ }
8159
+ },
8160
  "node_modules/web-vitals": {
8161
  "version": "4.2.4",
8162
  "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz",
 
8212
  "version": "2.0.2",
8213
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
8214
  "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
8215
+ "devOptional": true,
8216
  "license": "ISC",
8217
  "dependencies": {
8218
  "isexe": "^2.0.0"
 
8251
  "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
8252
  }
8253
  },
8254
+ "node_modules/wrap-ansi-cjs": {
8255
+ "name": "wrap-ansi",
8256
+ "version": "7.0.0",
8257
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
8258
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
8259
+ "license": "MIT",
8260
+ "optional": true,
8261
+ "peer": true,
8262
+ "dependencies": {
8263
+ "ansi-styles": "^4.0.0",
8264
+ "string-width": "^4.1.0",
8265
+ "strip-ansi": "^6.0.0"
8266
+ },
8267
+ "engines": {
8268
+ "node": ">=10"
8269
+ },
8270
+ "funding": {
8271
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
8272
+ }
8273
+ },
8274
  "node_modules/wrappy": {
8275
  "version": "1.0.2",
8276
  "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
 
8362
  "version": "0.1.0",
8363
  "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
8364
  "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
8365
+ "devOptional": true,
8366
  "license": "MIT",
8367
  "engines": {
8368
  "node": ">=10"
package.json CHANGED
@@ -13,21 +13,27 @@
13
  "@simplewebauthn/browser": "^13.2.2",
14
  "axios": "^1.13.2",
15
  "bcrypt": "^6.0.0",
 
 
 
16
  "cors": "^2.8.5",
17
  "dotenv": "^17.2.3",
18
  "express": "^5.2.1",
19
  "firebase": "^12.7.0",
 
20
  "jsonwebtoken": "^9.0.3",
21
  "leaflet": "^1.9.4",
22
  "lucide-react": "^0.562.0",
23
- "mongoose": "^9.1.0",
24
  "multer": "^2.0.2",
 
25
  "react": "^19.2.0",
26
  "react-dom": "^19.2.0",
27
  "react-leaflet": "^5.0.0",
28
  "react-markdown": "^10.1.0",
29
  "socket.io": "^4.8.3",
30
- "socket.io-client": "^4.8.3"
 
31
  },
32
  "devDependencies": {
33
  "@eslint/js": "^9.39.1",
 
13
  "@simplewebauthn/browser": "^13.2.2",
14
  "axios": "^1.13.2",
15
  "bcrypt": "^6.0.0",
16
+ "bcryptjs": "^3.0.3",
17
+ "body-parser": "^2.2.1",
18
+ "cloudinary": "^2.8.0",
19
  "cors": "^2.8.5",
20
  "dotenv": "^17.2.3",
21
  "express": "^5.2.1",
22
  "firebase": "^12.7.0",
23
+ "firebase-admin": "^13.6.0",
24
  "jsonwebtoken": "^9.0.3",
25
  "leaflet": "^1.9.4",
26
  "lucide-react": "^0.562.0",
27
+ "mongoose": "^9.1.1",
28
  "multer": "^2.0.2",
29
+ "nodemailer": "^7.0.12",
30
  "react": "^19.2.0",
31
  "react-dom": "^19.2.0",
32
  "react-leaflet": "^5.0.0",
33
  "react-markdown": "^10.1.0",
34
  "socket.io": "^4.8.3",
35
+ "socket.io-client": "^4.8.3",
36
+ "ws": "^8.18.3"
37
  },
38
  "devDependencies": {
39
  "@eslint/js": "^9.39.1",
server.js CHANGED
@@ -1,20 +1,89 @@
1
- // Update: Wed Dec 31 21:10:37 WAT 2025
2
- // Update: Wed Dec 31 21:28:01 WAT 2025
3
- // Update: Wed Dec 31 21:41:03 WAT 2025
4
- // Update: Wed Dec 31 21:47:16 WAT 2025
5
- // Update: Wed Dec 31 22:00:33 WAT 2025
6
- // Update: Wed Dec 31 22:05:32 WAT 2025
7
- // Update: Wed Dec 31 22:30:58 WAT 2025
8
- // Update: Wed Dec 31 23:18:39 WAT 2025
9
- // Update: Wed Dec 31 23:53:08 WAT 2025
10
- // Update: Thu Jan 1 00:28:45 WAT 2026
11
- // Update: Thu Jan 1 00:34:43 WAT 2026
12
- // Update: Thu Jan 1 00:39:10 WAT 2026
13
- // Update: Thu Jan 1 00:42:14 WAT 2026
14
- // Update: Thu Jan 1 00:44:58 WAT 2026
15
- // Update: Thu Jan 1 00:49:09 WAT 2026
16
- // Update: Thu Jan 1 00:50:31 WAT 2026
17
- // Update: Thu Jan 1 00:53:13 WAT 2026
18
- // Update: Thu Jan 1 00:56:25 WAT 2026
19
- // Update: Thu Jan 1 00:59:32 WAT 2026
20
- // Update: Thu Jan 1 01:05:11 WAT 2026
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import 'dotenv/config';
2
+ import express from 'express';
3
+ import mongoose from 'mongoose';
4
+ import cors from 'cors';
5
+ import bcrypt from 'bcryptjs';
6
+ import jwt from 'jsonwebtoken';
7
+ import nodemailer from 'nodemailer';
8
+ import crypto from 'crypto';
9
+ import path from 'path';
10
+ import fs from 'fs';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ const app = express();
17
+ app.use(cors());
18
+ app.use(express.json());
19
+
20
+ // --- CONNEXION MONGODB ---
21
+ mongoose.connect(process.env.MONGO_URI)
22
+ .then(() => console.log('✅ MongoDB Connecté'))
23
+ .catch(err => console.error('❌ Erreur DB:', err));
24
+
25
+ // --- CONFIGURATION NODEMAILER (CORRIGÉE) ---
26
+ const transporter = nodemailer.createTransport({
27
+ host: 'smtp.gmail.com',
28
+ port: 465,
29
+ secure: true, // Utilisation du port SSL 465
30
+ auth: {
31
+ user: process.env.EMAIL_USER,
32
+ pass: process.env.EMAIL_PASS
33
+ },
34
+ tls: {
35
+ rejectUnauthorized: false // Aide à passer outre certains blocages réseau
36
+ }
37
+ });
38
+
39
+ // Vérification immédiate
40
+ transporter.verify((error) => {
41
+ if (error) {
42
+ console.error('❌ Erreur SMTP Persistante:', error.message);
43
+ } else {
44
+ console.log('📧 Serveur SMTP authentifié avec succès !');
45
+ }
46
+ });
47
+
48
+ const User = mongoose.model('User', new mongoose.Schema({
49
+ email: { type: String, unique: true, required: true },
50
+ password: { type: String, required: true },
51
+ otp: String,
52
+ otpExpires: Date
53
+ }));
54
+
55
+ // --- ROUTE REGISTER ---
56
+ app.post('/api/auth/register', async (req, res) => {
57
+ const { email, password } = req.body;
58
+ const otp = Math.floor(100000 + Math.random() * 900000).toString();
59
+
60
+ try {
61
+ let user = await User.findOne({ email });
62
+ if (!user) {
63
+ const hashedPassword = await bcrypt.hash(password, 10);
64
+ user = new User({ email, password: hashedPassword, otp, otpExpires: Date.now() + 600000 });
65
+ } else {
66
+ user.otp = otp;
67
+ user.otpExpires = Date.now() + 600000;
68
+ }
69
+ await user.save();
70
+
71
+ await transporter.sendMail({
72
+ from: `"Kibali AI" <${process.env.EMAIL_USER}>`,
73
+ to: email,
74
+ subject: `Code de vérification : ${otp}`,
75
+ html: `<div style="text-align:center; padding:20px; border:2px solid #10b981;">
76
+ <h1>Votre code Kibali</h1>
77
+ <p style="font-size:30px; font-weight:bold;">${otp}</p>
78
+ </div>`
79
+ });
80
+
81
+ res.json({ message: "OTP envoyé" });
82
+ } catch (err) {
83
+ console.error("Erreur lors du register:", err);
84
+ res.status(500).json({ error: "Erreur serveur ou SMTP" });
85
+ }
86
+ });
87
+
88
+ const PORT = process.env.PORT || 5000;
89
+ app.listen(PORT, () => console.log(`🚀 Serveur actif sur le port ${PORT}`));
src/App.jsx CHANGED
@@ -3,8 +3,33 @@ import axios from 'axios';
3
  import {
4
  Send, FileText, Upload, Globe, MapPin,
5
  Loader2, Trash2, Image as ImageIcon, Search, Brain, ChevronDown, ChevronUp, User,
6
- Database, Clock, TrendingUp, AlertCircle, CheckCircle, Zap
 
7
  } from 'lucide-react';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  const API_BASE = "https://belikanm-kibali-api.hf.space";
10
  const LOGO_PATH = "/kibali_logo.svg";
@@ -18,18 +43,33 @@ function App() {
18
  doc_chunks: 0,
19
  memory_entries: 0,
20
  current_subject: null,
21
- subject_message_count: 0
 
 
22
  });
23
  const [showThinking, setShowThinking] = useState({});
24
  const [uploadProgress, setUploadProgress] = useState(null);
 
 
 
25
  const scrollRef = useRef(null);
26
  const pollingInterval = useRef(null);
27
 
28
- // Récupération du status backend au démarrage et périodiquement
 
 
 
 
 
 
 
 
 
 
29
  useEffect(() => {
30
  fetchStatus();
31
- pollingInterval.current = setInterval(fetchStatus, 10000); // Toutes les 10 secondes
32
-
33
  return () => {
34
  if (pollingInterval.current) {
35
  clearInterval(pollingInterval.current);
@@ -46,6 +86,27 @@ function App() {
46
  }
47
  };
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  // Auto-scroll vers le bas
50
  useEffect(() => {
51
  scrollRef.current?.scrollIntoView({ behavior: "smooth" });
@@ -55,7 +116,12 @@ function App() {
55
  const handleSend = async () => {
56
  if (!input.trim() || loading) return;
57
 
58
- const userMsg = { role: "user", content: input.trim() };
 
 
 
 
 
59
  setMessages(prev => [...prev, userMsg]);
60
  setInput("");
61
  setLoading(true);
@@ -68,7 +134,7 @@ function App() {
68
  city: "Libreville",
69
  thinking_mode: true
70
  }, {
71
- timeout: 120000 // 120 secondes pour les requêtes complexes
72
  });
73
 
74
  const aiResponse = response.data.response || "Réponse reçue du serveur.";
@@ -83,16 +149,15 @@ function App() {
83
  timestamp: new Date().toISOString()
84
  }]);
85
 
86
- // Mise à jour du status après la réponse
87
  fetchStatus();
88
  } catch (error) {
89
  console.error("Erreur lors de l'appel au backend:", error);
90
  let errorMsg = "Erreur : impossible de contacter le serveur IA.";
91
-
92
  if (error.code === 'ERR_NETWORK') {
93
- errorMsg = "⚠️ Serveur injoignable. Vérifiez que votre backend est lancé sur http://localhost:8000";
94
  } else if (error.code === 'ECONNABORTED') {
95
- errorMsg = "⏱️ Timeout : la requête a pris trop de temps. Le modèle est peut-être surchargé.";
96
  } else if (error.response?.status === 400) {
97
  errorMsg = `❌ Erreur de requête : ${error.response.data.detail || 'Format invalide'}`;
98
  } else if (error.response?.status === 500) {
@@ -112,7 +177,7 @@ function App() {
112
  }
113
  };
114
 
115
- // Upload de fichiers PDF avec feedback de progression
116
  const handleFileUpload = async (e) => {
117
  const files = Array.from(e.target.files);
118
  if (!files.length) return;
@@ -126,7 +191,7 @@ function App() {
126
  try {
127
  const res = await axios.post(`${API_BASE}/upload`, formData, {
128
  headers: { 'Content-Type': 'multipart/form-data' },
129
- timeout: 180000, // 3 minutes pour les gros PDFs
130
  onUploadProgress: (progressEvent) => {
131
  const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
132
  setUploadProgress(prev => ({ ...prev, percent: percentCompleted }));
@@ -137,7 +202,6 @@ function App() {
137
  const filesProcessed = res.data.files_processed || 0;
138
  const totalChunks = res.data.total_doc_chunks || 0;
139
 
140
- // Mise à jour du status immédiate
141
  setStatus(prev => ({ ...prev, doc_chunks: totalChunks }));
142
 
143
  setMessages(prev => [...prev, {
@@ -147,12 +211,10 @@ function App() {
147
  timestamp: new Date().toISOString()
148
  }]);
149
 
150
- // Refresh complet du status
151
  fetchStatus();
152
  } catch (err) {
153
  console.error("Erreur upload:", err);
154
  let errorMsg = "❌ Échec de l'import des documents.";
155
-
156
  if (err.code === 'ECONNABORTED') {
157
  errorMsg += " Timeout : les fichiers sont peut-être trop volumineux.";
158
  } else if (err.response?.data?.detail) {
@@ -172,18 +234,15 @@ function App() {
172
  }
173
  };
174
 
175
- // Réinitialisation du chat ET de la mémoire
176
  const handleReset = async () => {
177
- if (!window.confirm("Voulez-vous réinitialiser la conversation ET effacer la mémoire du modèle ?")) {
178
- return;
179
- }
180
 
181
  try {
182
- // Appeler l'endpoint de clear memory
183
  await axios.post(`${API_BASE}/clear-memory`, {}, { timeout: 5000 });
184
  setMessages([]);
185
  fetchStatus();
186
-
187
  setMessages([{
188
  role: "assistant",
189
  content: "✅ Conversation et mémoire réinitialisées avec succès.",
@@ -195,17 +254,16 @@ function App() {
195
  setMessages([{
196
  role: "assistant",
197
  content: "⚠️ Chat réinitialisé, mais impossible de contacter le serveur pour effacer la mémoire.",
198
- error: true
 
199
  }]);
200
  }
201
  };
202
 
203
- // Toggle thinking pour chaque message
204
  const toggleThinking = (msgIndex) => {
205
  setShowThinking(prev => ({ ...prev, [msgIndex]: !prev[msgIndex] }));
206
  };
207
 
208
- // Formatage du temps relatif
209
  const formatTimeAgo = (timestamp) => {
210
  if (!timestamp) return "";
211
  const seconds = Math.floor((new Date() - new Date(timestamp)) / 1000);
@@ -230,7 +288,34 @@ function App() {
230
  inputField: { flex: 1, background: 'transparent', border: 'none', color: 'white', padding: '0.8rem', outline: 'none', fontSize: '1rem' },
231
  sendBtn: { backgroundColor: '#10b981', color: 'white', border: 'none', borderRadius: '1rem', width: '45px', height: '45px', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', transition: 'all 0.2s' },
232
  toolBadge: { display: 'flex', alignItems: 'center', gap: '6px', fontSize: '11px', backgroundColor: '#020617', padding: '6px 12px', borderRadius: '10px', border: '1px solid #1e293b', color: '#94a3b8' },
233
- statCard: { backgroundColor: 'rgba(2, 6, 23, 0.5)', borderRadius: '1rem', padding: '1rem', border: '1px solid #1e293b', marginBottom: '0.8rem' }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  };
235
 
236
  return (
@@ -252,7 +337,97 @@ function App() {
252
  </div>
253
 
254
  <div style={{ padding: '2rem', flex: 1, display: 'flex', flexDirection: 'column', gap: '2rem' }}>
255
- {/* Upload de documents */}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  <div>
257
  <h2 style={{ fontSize: '11px', color: '#475569', textTransform: 'uppercase', letterSpacing: '1.5px', marginBottom: '1rem', fontWeight: '800' }}>
258
  📚 Documents
@@ -298,13 +473,12 @@ function App() {
298
  </label>
299
  </div>
300
 
301
- {/* Statistiques enrichies */}
302
  <div>
303
  <h3 style={{ fontSize: '11px', color: '#475569', textTransform: 'uppercase', marginBottom: '1rem', fontWeight: '800', letterSpacing: '1.5px' }}>
304
  📊 Statistiques
305
  </h3>
306
-
307
- {/* Base de connaissances */}
308
  <div style={styles.statCard}>
309
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
310
  <span style={{ color: '#64748b', fontSize: '12px', display: 'flex', alignItems: 'center', gap: '6px' }}>
@@ -319,7 +493,6 @@ function App() {
319
  </div>
320
  </div>
321
 
322
- {/* Mémoire conversationnelle */}
323
  <div style={styles.statCard}>
324
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
325
  <span style={{ color: '#64748b', fontSize: '12px', display: 'flex', alignItems: 'center', gap: '6px' }}>
@@ -334,7 +507,6 @@ function App() {
334
  </div>
335
  </div>
336
 
337
- {/* Contexte conversationnel */}
338
  {status.current_subject && (
339
  <div style={styles.statCard}>
340
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
@@ -351,7 +523,6 @@ function App() {
351
  </div>
352
  )}
353
 
354
- {/* Localisation */}
355
  <div style={styles.statCard}>
356
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
357
  <span style={{ color: '#64748b', fontSize: '12px' }}>Position</span>
@@ -361,7 +532,6 @@ function App() {
361
  </div>
362
  </div>
363
 
364
- {/* Santé du système */}
365
  <div style={styles.statCard}>
366
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
367
  <span style={{ color: '#64748b', fontSize: '12px', display: 'flex', alignItems: 'center', gap: '6px' }}>
@@ -431,6 +601,43 @@ function App() {
431
  <p style={{ color: '#64748b', maxWidth: '450px', lineHeight: '1.7', fontSize: '1.1rem' }}>
432
  Assistant IA expert du Gabon avec mémoire contextuelle et analyse documentaire avancée.
433
  </p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  <div style={{ display: 'flex', gap: '1rem', marginTop: '2rem' }}>
435
  <div style={{ textAlign: 'center' }}>
436
  <div style={{ fontSize: '2rem', fontWeight: 'bold', color: '#10b981' }}>{status.doc_chunks}</div>
@@ -456,10 +663,27 @@ function App() {
456
  justifyContent: 'center',
457
  backgroundColor: m.role === 'user' ? '#059669' : m.error ? '#7f1d1d' : m.success ? '#064e3b' : '#1e293b',
458
  flexShrink: 0,
459
- border: '1px solid #334155'
 
460
  }}>
461
  {m.role === 'user' ? (
462
- <User size={24} color="white" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
463
  ) : m.error ? (
464
  <AlertCircle size={24} color="#ef4444" />
465
  ) : m.success ? (
@@ -470,7 +694,6 @@ function App() {
470
  </div>
471
 
472
  <div style={{ display: 'flex', flexDirection: 'column', gap: '0.8rem', width: '100%' }}>
473
- {/* Informations contextuelles */}
474
  {m.role === 'assistant' && !m.error && !m.success && m.context_info && (
475
  <div style={{ backgroundColor: 'rgba(30, 41, 59, 0.3)', borderRadius: '12px', padding: '10px 14px', border: '1px solid #1e293b' }}>
476
  <button
@@ -482,7 +705,7 @@ function App() {
482
  </span>
483
  {showThinking[i] ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
484
  </button>
485
-
486
  {showThinking[i] && (
487
  <>
488
  <div style={{ display: 'flex', gap: '8px', marginTop: '12px', flexWrap: 'wrap' }}>
@@ -503,7 +726,6 @@ function App() {
503
  </div>
504
  </div>
505
 
506
- {/* Détails du contexte */}
507
  <div style={{ marginTop: '12px', fontSize: '11px', color: '#64748b', padding: '10px', backgroundColor: '#020617', borderRadius: '8px' }}>
508
  {m.context_info.subject_keywords?.length > 0 && (
509
  <div style={{ marginBottom: '8px' }}>
@@ -526,7 +748,6 @@ function App() {
526
  </div>
527
  )}
528
 
529
- {/* Bulle de message */}
530
  <div style={{
531
  ...(m.role === 'user' ? styles.userBubble : m.error ? styles.errorBubble : m.success ? styles.successBubble : styles.aiBubble),
532
  position: 'relative'
@@ -541,14 +762,13 @@ function App() {
541
  )}
542
  </div>
543
 
544
- {/* Images */}
545
  {m.images && m.images.length > 0 && (
546
  <div style={{ display: 'flex', gap: '12px', marginTop: '8px', overflowX: 'auto', paddingBottom: '10px' }}>
547
  {m.images.map((img, idx) => (
548
  <div key={idx} style={{ flexShrink: 0, position: 'relative', borderRadius: '1.2rem', overflow: 'hidden', border: '2px solid #334155', backgroundColor: '#0f172a' }}>
549
- <img
550
- src={img}
551
- alt={`Image ${idx + 1}`}
552
  style={{ height: '180px', width: '280px', objectFit: 'cover' }}
553
  onError={(e) => {
554
  e.target.style.display = 'none';
@@ -597,28 +817,28 @@ function App() {
597
  <Search size={22} color="#475569" style={{ marginRight: '10px' }} />
598
  <input
599
  style={styles.inputField}
600
- placeholder="Posez votre question sur le Gabon, vos documents ou l'actualité..."
601
  value={input}
602
  onChange={(e) => setInput(e.target.value)}
603
  onKeyDown={(e) => {
604
- if (e.key === 'Enter' && !e.shiftKey) {
605
  e.preventDefault();
606
  handleSend();
607
  }
608
  }}
609
- disabled={loading}
610
  />
611
  <button
612
- style={{
613
- ...styles.sendBtn,
614
- opacity: input.trim() && !loading ? 1 : 0.4,
615
- cursor: input.trim() && !loading ? 'pointer' : 'not-allowed',
616
- transform: input.trim() && !loading ? 'scale(1)' : 'scale(0.95)'
617
  }}
618
  onClick={handleSend}
619
- disabled={loading || !input.trim()}
620
  onMouseEnter={(e) => {
621
- if (input.trim() && !loading) {
622
  e.target.style.backgroundColor = '#059669';
623
  e.target.style.transform = 'scale(1.05)';
624
  }
 
3
  import {
4
  Send, FileText, Upload, Globe, MapPin,
5
  Loader2, Trash2, Image as ImageIcon, Search, Brain, ChevronDown, ChevronUp, User,
6
+ Database, Clock, TrendingUp, AlertCircle, CheckCircle, Zap,
7
+ LogOut
8
  } from 'lucide-react';
9
+ import { initializeApp } from 'firebase/app';
10
+ import {
11
+ getAuth,
12
+ GoogleAuthProvider,
13
+ signInWithPopup,
14
+ signOut,
15
+ onAuthStateChanged
16
+ } from 'firebase/auth';
17
+
18
+ // Configuration Firebase
19
+ const firebaseConfig = {
20
+ apiKey: import.meta.env.VITE_FIREBASE_API_KEY || "AIzaSyCel4qvAtZomh4aQOCArCLIYSYmeZ4Qbig",
21
+ authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || "sevenstatut.firebaseapp.com",
22
+ databaseURL: import.meta.env.VITE_FIREBASE_DATABASE_URL || "https://sevenstatut-default-rtdb.firebaseio.com",
23
+ projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || "sevenstatut",
24
+ storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || "sevenstatut.firebasestorage.app",
25
+ messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || "838268990346",
26
+ appId: import.meta.env.VITE_FIREBASE_APP_ID || "1:838268990346:web:dba8702c39e82981704e73"
27
+ };
28
+
29
+ // Initialiser Firebase
30
+ const app = initializeApp(firebaseConfig);
31
+ const auth = getAuth(app);
32
+ const googleProvider = new GoogleAuthProvider();
33
 
34
  const API_BASE = "https://belikanm-kibali-api.hf.space";
35
  const LOGO_PATH = "/kibali_logo.svg";
 
43
  doc_chunks: 0,
44
  memory_entries: 0,
45
  current_subject: null,
46
+ subject_message_count: 0,
47
+ torch_cuda_available: false,
48
+ status: 'unknown'
49
  });
50
  const [showThinking, setShowThinking] = useState({});
51
  const [uploadProgress, setUploadProgress] = useState(null);
52
+ const [user, setUser] = useState(null);
53
+ const [authLoading, setAuthLoading] = useState(true);
54
+
55
  const scrollRef = useRef(null);
56
  const pollingInterval = useRef(null);
57
 
58
+ // Gestion de l'authentification
59
+ useEffect(() => {
60
+ const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
61
+ setUser(firebaseUser);
62
+ setAuthLoading(false);
63
+ });
64
+
65
+ return () => unsubscribe();
66
+ }, []);
67
+
68
+ // Récupération du statut du backend au démarrage et toutes les 10 secondes
69
  useEffect(() => {
70
  fetchStatus();
71
+ pollingInterval.current = setInterval(fetchStatus, 10000);
72
+
73
  return () => {
74
  if (pollingInterval.current) {
75
  clearInterval(pollingInterval.current);
 
86
  }
87
  };
88
 
89
+ // Connexion Google
90
+ const handleGoogleLogin = async () => {
91
+ try {
92
+ const result = await signInWithPopup(auth, googleProvider);
93
+ setUser(result.user);
94
+ } catch (error) {
95
+ console.error("Erreur de connexion Google:", error);
96
+ alert(`Erreur de connexion: ${error.message}`);
97
+ }
98
+ };
99
+
100
+ // Déconnexion
101
+ const handleLogout = async () => {
102
+ try {
103
+ await signOut(auth);
104
+ setUser(null);
105
+ } catch (error) {
106
+ console.error("Erreur de déconnexion:", error);
107
+ }
108
+ };
109
+
110
  // Auto-scroll vers le bas
111
  useEffect(() => {
112
  scrollRef.current?.scrollIntoView({ behavior: "smooth" });
 
116
  const handleSend = async () => {
117
  if (!input.trim() || loading) return;
118
 
119
+ const userMsg = {
120
+ role: "user",
121
+ content: input.trim(),
122
+ userPhoto: user?.photoURL || null,
123
+ userName: user?.displayName || "Utilisateur"
124
+ };
125
  setMessages(prev => [...prev, userMsg]);
126
  setInput("");
127
  setLoading(true);
 
134
  city: "Libreville",
135
  thinking_mode: true
136
  }, {
137
+ timeout: 120000
138
  });
139
 
140
  const aiResponse = response.data.response || "Réponse reçue du serveur.";
 
149
  timestamp: new Date().toISOString()
150
  }]);
151
 
 
152
  fetchStatus();
153
  } catch (error) {
154
  console.error("Erreur lors de l'appel au backend:", error);
155
  let errorMsg = "Erreur : impossible de contacter le serveur IA.";
156
+
157
  if (error.code === 'ERR_NETWORK') {
158
+ errorMsg = "⚠️ Serveur injoignable. Vérifiez que votre backend est lancé.";
159
  } else if (error.code === 'ECONNABORTED') {
160
+ errorMsg = "⏱️ Timeout : la requête a pris trop de temps.";
161
  } else if (error.response?.status === 400) {
162
  errorMsg = `❌ Erreur de requête : ${error.response.data.detail || 'Format invalide'}`;
163
  } else if (error.response?.status === 500) {
 
177
  }
178
  };
179
 
180
+ // Upload de fichiers PDF
181
  const handleFileUpload = async (e) => {
182
  const files = Array.from(e.target.files);
183
  if (!files.length) return;
 
191
  try {
192
  const res = await axios.post(`${API_BASE}/upload`, formData, {
193
  headers: { 'Content-Type': 'multipart/form-data' },
194
+ timeout: 180000,
195
  onUploadProgress: (progressEvent) => {
196
  const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
197
  setUploadProgress(prev => ({ ...prev, percent: percentCompleted }));
 
202
  const filesProcessed = res.data.files_processed || 0;
203
  const totalChunks = res.data.total_doc_chunks || 0;
204
 
 
205
  setStatus(prev => ({ ...prev, doc_chunks: totalChunks }));
206
 
207
  setMessages(prev => [...prev, {
 
211
  timestamp: new Date().toISOString()
212
  }]);
213
 
 
214
  fetchStatus();
215
  } catch (err) {
216
  console.error("Erreur upload:", err);
217
  let errorMsg = "❌ Échec de l'import des documents.";
 
218
  if (err.code === 'ECONNABORTED') {
219
  errorMsg += " Timeout : les fichiers sont peut-être trop volumineux.";
220
  } else if (err.response?.data?.detail) {
 
234
  }
235
  };
236
 
237
+ // Réinitialisation complète (chat + mémoire)
238
  const handleReset = async () => {
239
+ if (!window.confirm("Voulez-vous réinitialiser la conversation ET effacer la mémoire du modèle ?")) return;
 
 
240
 
241
  try {
 
242
  await axios.post(`${API_BASE}/clear-memory`, {}, { timeout: 5000 });
243
  setMessages([]);
244
  fetchStatus();
245
+
246
  setMessages([{
247
  role: "assistant",
248
  content: "✅ Conversation et mémoire réinitialisées avec succès.",
 
254
  setMessages([{
255
  role: "assistant",
256
  content: "⚠️ Chat réinitialisé, mais impossible de contacter le serveur pour effacer la mémoire.",
257
+ error: true,
258
+ timestamp: new Date().toISOString()
259
  }]);
260
  }
261
  };
262
 
 
263
  const toggleThinking = (msgIndex) => {
264
  setShowThinking(prev => ({ ...prev, [msgIndex]: !prev[msgIndex] }));
265
  };
266
 
 
267
  const formatTimeAgo = (timestamp) => {
268
  if (!timestamp) return "";
269
  const seconds = Math.floor((new Date() - new Date(timestamp)) / 1000);
 
288
  inputField: { flex: 1, background: 'transparent', border: 'none', color: 'white', padding: '0.8rem', outline: 'none', fontSize: '1rem' },
289
  sendBtn: { backgroundColor: '#10b981', color: 'white', border: 'none', borderRadius: '1rem', width: '45px', height: '45px', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', transition: 'all 0.2s' },
290
  toolBadge: { display: 'flex', alignItems: 'center', gap: '6px', fontSize: '11px', backgroundColor: '#020617', padding: '6px 12px', borderRadius: '10px', border: '1px solid #1e293b', color: '#94a3b8' },
291
+ statCard: { backgroundColor: 'rgba(2, 6, 23, 0.5)', borderRadius: '1rem', padding: '1rem', border: '1px solid #1e293b', marginBottom: '0.8rem' },
292
+ googleBtn: {
293
+ width: '100%',
294
+ padding: '12px 16px',
295
+ backgroundColor: '#0f172a',
296
+ border: '1px solid #334155',
297
+ borderRadius: '12px',
298
+ color: '#f1f5f9',
299
+ display: 'flex',
300
+ alignItems: 'center',
301
+ justifyContent: 'center',
302
+ gap: '10px',
303
+ cursor: 'pointer',
304
+ fontWeight: '600',
305
+ fontSize: '14px',
306
+ transition: 'all 0.2s',
307
+ marginBottom: '1rem'
308
+ },
309
+ userProfile: {
310
+ display: 'flex',
311
+ alignItems: 'center',
312
+ gap: '12px',
313
+ padding: '12px 16px',
314
+ backgroundColor: 'rgba(2, 6, 23, 0.5)',
315
+ borderRadius: '12px',
316
+ border: '1px solid #334155',
317
+ marginBottom: '1rem'
318
+ }
319
  };
320
 
321
  return (
 
337
  </div>
338
 
339
  <div style={{ padding: '2rem', flex: 1, display: 'flex', flexDirection: 'column', gap: '2rem' }}>
340
+ {/* Section Connexion */}
341
+ {authLoading ? (
342
+ <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '80px' }}>
343
+ <Loader2 className="animate-spin" color="#10b981" size={24} />
344
+ </div>
345
+ ) : user ? (
346
+ <div style={styles.userProfile}>
347
+ <div style={{ position: 'relative' }}>
348
+ <img
349
+ src={user.photoURL}
350
+ alt={user.displayName || "Utilisateur"}
351
+ style={{
352
+ width: '50px',
353
+ height: '50px',
354
+ borderRadius: '50%',
355
+ border: '2px solid #10b981'
356
+ }}
357
+ onError={(e) => {
358
+ e.target.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.displayName || "User")}&background=059669&color=fff`;
359
+ }}
360
+ />
361
+ <div style={{
362
+ position: 'absolute',
363
+ bottom: 0,
364
+ right: 0,
365
+ width: '12px',
366
+ height: '12px',
367
+ backgroundColor: '#10b981',
368
+ borderRadius: '50%',
369
+ border: '2px solid #0f172a'
370
+ }} />
371
+ </div>
372
+ <div style={{ flex: 1 }}>
373
+ <div style={{ fontWeight: '600', fontSize: '15px', color: '#f1f5f9' }}>
374
+ {user.displayName || "Utilisateur"}
375
+ </div>
376
+ <div style={{ fontSize: '12px', color: '#64748b', marginTop: '4px' }}>
377
+ {user.email}
378
+ </div>
379
+ </div>
380
+ <button
381
+ onClick={handleLogout}
382
+ style={{
383
+ backgroundColor: 'transparent',
384
+ border: '1px solid #334155',
385
+ borderRadius: '8px',
386
+ width: '36px',
387
+ height: '36px',
388
+ display: 'flex',
389
+ alignItems: 'center',
390
+ justifyContent: 'center',
391
+ cursor: 'pointer',
392
+ color: '#94a3b8',
393
+ transition: 'all 0.2s'
394
+ }}
395
+ onMouseEnter={(e) => {
396
+ e.target.style.borderColor = '#ef4444';
397
+ e.target.style.color = '#ef4444';
398
+ }}
399
+ onMouseLeave={(e) => {
400
+ e.target.style.borderColor = '#334155';
401
+ e.target.style.color = '#94a3b8';
402
+ }}
403
+ >
404
+ <LogOut size={18} />
405
+ </button>
406
+ </div>
407
+ ) : (
408
+ <button
409
+ onClick={handleGoogleLogin}
410
+ style={styles.googleBtn}
411
+ onMouseEnter={(e) => {
412
+ e.target.style.backgroundColor = '#1e293b';
413
+ e.target.style.borderColor = '#475569';
414
+ }}
415
+ onMouseLeave={(e) => {
416
+ e.target.style.backgroundColor = '#0f172a';
417
+ e.target.style.borderColor = '#334155';
418
+ }}
419
+ >
420
+ <svg width="20" height="20" viewBox="0 0 24 24">
421
+ <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
422
+ <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
423
+ <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
424
+ <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
425
+ </svg>
426
+ Connexion Google
427
+ </button>
428
+ )}
429
+
430
+ {/* Upload */}
431
  <div>
432
  <h2 style={{ fontSize: '11px', color: '#475569', textTransform: 'uppercase', letterSpacing: '1.5px', marginBottom: '1rem', fontWeight: '800' }}>
433
  📚 Documents
 
473
  </label>
474
  </div>
475
 
476
+ {/* Statistiques */}
477
  <div>
478
  <h3 style={{ fontSize: '11px', color: '#475569', textTransform: 'uppercase', marginBottom: '1rem', fontWeight: '800', letterSpacing: '1.5px' }}>
479
  📊 Statistiques
480
  </h3>
481
+
 
482
  <div style={styles.statCard}>
483
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
484
  <span style={{ color: '#64748b', fontSize: '12px', display: 'flex', alignItems: 'center', gap: '6px' }}>
 
493
  </div>
494
  </div>
495
 
 
496
  <div style={styles.statCard}>
497
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
498
  <span style={{ color: '#64748b', fontSize: '12px', display: 'flex', alignItems: 'center', gap: '6px' }}>
 
507
  </div>
508
  </div>
509
 
 
510
  {status.current_subject && (
511
  <div style={styles.statCard}>
512
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
 
523
  </div>
524
  )}
525
 
 
526
  <div style={styles.statCard}>
527
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
528
  <span style={{ color: '#64748b', fontSize: '12px' }}>Position</span>
 
532
  </div>
533
  </div>
534
 
 
535
  <div style={styles.statCard}>
536
  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
537
  <span style={{ color: '#64748b', fontSize: '12px', display: 'flex', alignItems: 'center', gap: '6px' }}>
 
601
  <p style={{ color: '#64748b', maxWidth: '450px', lineHeight: '1.7', fontSize: '1.1rem' }}>
602
  Assistant IA expert du Gabon avec mémoire contextuelle et analyse documentaire avancée.
603
  </p>
604
+ {!user && (
605
+ <div style={{ marginTop: '2rem' }}>
606
+ <button
607
+ onClick={handleGoogleLogin}
608
+ style={{
609
+ padding: '12px 24px',
610
+ backgroundColor: '#0f172a',
611
+ border: '1px solid #334155',
612
+ borderRadius: '12px',
613
+ color: '#f1f5f9',
614
+ display: 'flex',
615
+ alignItems: 'center',
616
+ gap: '10px',
617
+ cursor: 'pointer',
618
+ fontWeight: '600',
619
+ fontSize: '14px',
620
+ transition: 'all 0.2s'
621
+ }}
622
+ onMouseEnter={(e) => {
623
+ e.target.style.backgroundColor = '#1e293b';
624
+ e.target.style.borderColor = '#475569';
625
+ }}
626
+ onMouseLeave={(e) => {
627
+ e.target.style.backgroundColor = '#0f172a';
628
+ e.target.style.borderColor = '#334155';
629
+ }}
630
+ >
631
+ <svg width="20" height="20" viewBox="0 0 24 24">
632
+ <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
633
+ <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
634
+ <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
635
+ <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
636
+ </svg>
637
+ Connectez-vous pour commencer
638
+ </button>
639
+ </div>
640
+ )}
641
  <div style={{ display: 'flex', gap: '1rem', marginTop: '2rem' }}>
642
  <div style={{ textAlign: 'center' }}>
643
  <div style={{ fontSize: '2rem', fontWeight: 'bold', color: '#10b981' }}>{status.doc_chunks}</div>
 
663
  justifyContent: 'center',
664
  backgroundColor: m.role === 'user' ? '#059669' : m.error ? '#7f1d1d' : m.success ? '#064e3b' : '#1e293b',
665
  flexShrink: 0,
666
+ border: '1px solid #334155',
667
+ overflow: 'hidden'
668
  }}>
669
  {m.role === 'user' ? (
670
+ m.userPhoto ? (
671
+ <img
672
+ src={m.userPhoto}
673
+ alt={m.userName}
674
+ style={{
675
+ width: '100%',
676
+ height: '100%',
677
+ objectFit: 'cover'
678
+ }}
679
+ onError={(e) => {
680
+ e.target.style.display = 'none';
681
+ e.target.parentElement.innerHTML = `<div style="display:flex;align-items:center;justify-content:center;width:100%;height:100%;background-color:#059669;"><User size={24} color="white" /></div>`;
682
+ }}
683
+ />
684
+ ) : (
685
+ <User size={24} color="white" />
686
+ )
687
  ) : m.error ? (
688
  <AlertCircle size={24} color="#ef4444" />
689
  ) : m.success ? (
 
694
  </div>
695
 
696
  <div style={{ display: 'flex', flexDirection: 'column', gap: '0.8rem', width: '100%' }}>
 
697
  {m.role === 'assistant' && !m.error && !m.success && m.context_info && (
698
  <div style={{ backgroundColor: 'rgba(30, 41, 59, 0.3)', borderRadius: '12px', padding: '10px 14px', border: '1px solid #1e293b' }}>
699
  <button
 
705
  </span>
706
  {showThinking[i] ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
707
  </button>
708
+
709
  {showThinking[i] && (
710
  <>
711
  <div style={{ display: 'flex', gap: '8px', marginTop: '12px', flexWrap: 'wrap' }}>
 
726
  </div>
727
  </div>
728
 
 
729
  <div style={{ marginTop: '12px', fontSize: '11px', color: '#64748b', padding: '10px', backgroundColor: '#020617', borderRadius: '8px' }}>
730
  {m.context_info.subject_keywords?.length > 0 && (
731
  <div style={{ marginBottom: '8px' }}>
 
748
  </div>
749
  )}
750
 
 
751
  <div style={{
752
  ...(m.role === 'user' ? styles.userBubble : m.error ? styles.errorBubble : m.success ? styles.successBubble : styles.aiBubble),
753
  position: 'relative'
 
762
  )}
763
  </div>
764
 
 
765
  {m.images && m.images.length > 0 && (
766
  <div style={{ display: 'flex', gap: '12px', marginTop: '8px', overflowX: 'auto', paddingBottom: '10px' }}>
767
  {m.images.map((img, idx) => (
768
  <div key={idx} style={{ flexShrink: 0, position: 'relative', borderRadius: '1.2rem', overflow: 'hidden', border: '2px solid #334155', backgroundColor: '#0f172a' }}>
769
+ <img
770
+ src={img}
771
+ alt={`Image ${idx + 1}`}
772
  style={{ height: '180px', width: '280px', objectFit: 'cover' }}
773
  onError={(e) => {
774
  e.target.style.display = 'none';
 
817
  <Search size={22} color="#475569" style={{ marginRight: '10px' }} />
818
  <input
819
  style={styles.inputField}
820
+ placeholder={user ? "Posez votre question sur le Gabon, vos documents ou l'actualité..." : "Connectez-vous pour poser des questions..."}
821
  value={input}
822
  onChange={(e) => setInput(e.target.value)}
823
  onKeyDown={(e) => {
824
+ if (e.key === 'Enter' && !e.shiftKey && user) {
825
  e.preventDefault();
826
  handleSend();
827
  }
828
  }}
829
+ disabled={loading || !user}
830
  />
831
  <button
832
+ style={{
833
+ ...styles.sendBtn,
834
+ opacity: (input.trim() && !loading && user) ? 1 : 0.4,
835
+ cursor: (input.trim() && !loading && user) ? 'pointer' : 'not-allowed',
836
+ transform: (input.trim() && !loading && user) ? 'scale(1)' : 'scale(0.95)'
837
  }}
838
  onClick={handleSend}
839
+ disabled={loading || !input.trim() || !user}
840
  onMouseEnter={(e) => {
841
+ if (input.trim() && !loading && user) {
842
  e.target.style.backgroundColor = '#059669';
843
  e.target.style.transform = 'scale(1.05)';
844
  }