]> git.digitality.be Git - pdw25-26/commitdiff
Refonte totale : nouvelle base de code propre
authorSteph Ponzo <ponzo.stephane2@gmail.com>
Mon, 23 Feb 2026 13:10:42 +0000 (14:10 +0100)
committerSteph Ponzo <ponzo.stephane2@gmail.com>
Mon, 23 Feb 2026 13:10:42 +0000 (14:10 +0100)
53 files changed:
.gitignore [deleted file]
App.tsx [deleted file]
app.json [deleted file]
assets/adaptive-icon.png [deleted file]
assets/favicon.png [deleted file]
assets/icon.png [deleted file]
assets/splash-icon.png [deleted file]
index.ts [deleted file]
package-lock.json [deleted file]
package.json [deleted file]
server/.env.example [new file with mode: 0644]
server/.gitignore [moved from system_notification/.gitignore with 100% similarity]
server/DOC-FRONTEND-SOCKET_POUR_OCEANE_ET_THIBAUD.md [new file with mode: 0644]
server/EXAMPLE-other-project.js [new file with mode: 0644]
server/config/db.js [new file with mode: 0644]
server/modules/alerts/adapters/mysql.adapter.js [new file with mode: 0644]
server/modules/alerts/alerts.controller.js [new file with mode: 0644]
server/modules/alerts/alerts.repo.js [new file with mode: 0644]
server/modules/alerts/alerts.router.js [new file with mode: 0644]
server/modules/alerts/alerts.service.js [new file with mode: 0644]
server/modules/alerts/channels/console.js [new file with mode: 0644]
server/modules/alerts/channels/discord.js [new file with mode: 0644]
server/modules/alerts/channels/mailer.js [new file with mode: 0644]
server/modules/alerts/channels/telegram.js [new file with mode: 0644]
server/modules/alerts/channels/web.js [new file with mode: 0644]
server/modules/alerts/index.js [new file with mode: 0644]
server/modules/alerts/init-alerts.js [new file with mode: 0644]
server/modules/alerts/socketManager.js [new file with mode: 0644]
server/modules/alerts/test-alerts.js [new file with mode: 0644]
server/modules/init-alerts.js [new file with mode: 0644]
server/package-lock.json [new file with mode: 0644]
server/package.json [new file with mode: 0644]
server/test-alerts.js [new file with mode: 0644]
shémaGIT.png [new file with mode: 0644]
src/mocks/dashboard.mock.ts [deleted file]
src/screens/DashboardScreen.tsx [deleted file]
src/services/dashboardService.ts [deleted file]
src/services/mockApi.ts [deleted file]
src/types/DashboardSummary.ts [deleted file]
src/utils/settingsStorage.ts [deleted file]
system_notification/README.md [deleted file]
system_notification/config/db.js [deleted file]
system_notification/package-lock.json [deleted file]
system_notification/package.json [deleted file]
system_notification/repositories/MySqlAlertRepository.js [deleted file]
system_notification/services/alerts/alertServices.js [deleted file]
system_notification/services/channels/discord.js [deleted file]
system_notification/services/channels/mailer.js [deleted file]
system_notification/services/channels/telegram.js [deleted file]
system_notification/services/channels/web.js [deleted file]
system_notification/test-connection.js [deleted file]
system_notification/test-mailer.js [deleted file]
tsconfig.json [deleted file]

diff --git a/.gitignore b/.gitignore
deleted file mode 100644 (file)
index d914c32..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
-
-# dependencies
-node_modules/
-
-# Expo
-.expo/
-dist/
-web-build/
-expo-env.d.ts
-
-# Native
-.kotlin/
-*.orig.*
-*.jks
-*.p8
-*.p12
-*.key
-*.mobileprovision
-
-# Metro
-.metro-health-check*
-
-# debug
-npm-debug.*
-yarn-debug.*
-yarn-error.*
-
-# macOS
-.DS_Store
-*.pem
-
-# local env files
-.env*.local
-
-# typescript
-*.tsbuildinfo
-
-# generated native folders
-/ios
-/android
diff --git a/App.tsx b/App.tsx
deleted file mode 100644 (file)
index bbfe4f3..0000000
--- a/App.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import DashboardScreen from "./src/screens/DashboardScreen";
-
-export default function App() {
-  return <DashboardScreen />;
-}
\ No newline at end of file
diff --git a/app.json b/app.json
deleted file mode 100644 (file)
index 2fe1a75..0000000
--- a/app.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "expo": {
-    "name": "conseiller-crypto-mobile",
-    "slug": "conseiller-crypto-mobile",
-    "version": "1.0.0",
-    "orientation": "portrait",
-    "icon": "./assets/icon.png",
-    "userInterfaceStyle": "light",
-    "newArchEnabled": true,
-    "splash": {
-      "image": "./assets/splash-icon.png",
-      "resizeMode": "contain",
-      "backgroundColor": "#ffffff"
-    },
-    "ios": {
-      "supportsTablet": true
-    },
-    "android": {
-      "adaptiveIcon": {
-        "foregroundImage": "./assets/adaptive-icon.png",
-        "backgroundColor": "#ffffff"
-      },
-      "edgeToEdgeEnabled": true,
-      "predictiveBackGestureEnabled": false
-    },
-    "web": {
-      "favicon": "./assets/favicon.png"
-    }
-  }
-}
diff --git a/assets/adaptive-icon.png b/assets/adaptive-icon.png
deleted file mode 100644 (file)
index 03d6f6b..0000000
Binary files a/assets/adaptive-icon.png and /dev/null differ
diff --git a/assets/favicon.png b/assets/favicon.png
deleted file mode 100644 (file)
index e75f697..0000000
Binary files a/assets/favicon.png and /dev/null differ
diff --git a/assets/icon.png b/assets/icon.png
deleted file mode 100644 (file)
index a0b1526..0000000
Binary files a/assets/icon.png and /dev/null differ
diff --git a/assets/splash-icon.png b/assets/splash-icon.png
deleted file mode 100644 (file)
index 03d6f6b..0000000
Binary files a/assets/splash-icon.png and /dev/null differ
diff --git a/index.ts b/index.ts
deleted file mode 100644 (file)
index 1d6e981..0000000
--- a/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { registerRootComponent } from 'expo';
-
-import App from './App';
-
-// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
-// It also ensures that whether you load the app in Expo Go or in a native build,
-// the environment is set up appropriately
-registerRootComponent(App);
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644 (file)
index d8dffc8..0000000
+++ /dev/null
@@ -1,8797 +0,0 @@
-{
-  "name": "conseiller-crypto-mobile",
-  "version": "1.0.0",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "conseiller-crypto-mobile",
-      "version": "1.0.0",
-      "dependencies": {
-        "expo": "~54.0.33",
-        "expo-status-bar": "~3.0.9",
-        "react": "19.1.0",
-        "react-native": "0.81.5",
-        "react-native-safe-area-context": "~5.6.0"
-      },
-      "devDependencies": {
-        "@types/react": "~19.1.0",
-        "typescript": "~5.9.2"
-      }
-    },
-    "node_modules/@0no-co/graphql.web": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz",
-      "integrity": "sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==",
-      "license": "MIT",
-      "peerDependencies": {
-        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
-      },
-      "peerDependenciesMeta": {
-        "graphql": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@babel/code-frame": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
-      "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/highlight": "^7.10.4"
-      }
-    },
-    "node_modules/@babel/compat-data": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
-      "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/core": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
-      "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.29.0",
-        "@babel/generator": "^7.29.0",
-        "@babel/helper-compilation-targets": "^7.28.6",
-        "@babel/helper-module-transforms": "^7.28.6",
-        "@babel/helpers": "^7.28.6",
-        "@babel/parser": "^7.29.0",
-        "@babel/template": "^7.28.6",
-        "@babel/traverse": "^7.29.0",
-        "@babel/types": "^7.29.0",
-        "@jridgewell/remapping": "^2.3.5",
-        "convert-source-map": "^2.0.0",
-        "debug": "^4.1.0",
-        "gensync": "^1.0.0-beta.2",
-        "json5": "^2.2.3",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/babel"
-      }
-    },
-    "node_modules/@babel/core/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/core/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/@babel/generator": {
-      "version": "7.29.1",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
-      "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/parser": "^7.29.0",
-        "@babel/types": "^7.29.0",
-        "@jridgewell/gen-mapping": "^0.3.12",
-        "@jridgewell/trace-mapping": "^0.3.28",
-        "jsesc": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-annotate-as-pure": {
-      "version": "7.27.3",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
-      "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.27.3"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-compilation-targets": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
-      "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/compat-data": "^7.28.6",
-        "@babel/helper-validator-option": "^7.27.1",
-        "browserslist": "^4.24.0",
-        "lru-cache": "^5.1.1",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/@babel/helper-create-class-features-plugin": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz",
-      "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.3",
-        "@babel/helper-member-expression-to-functions": "^7.28.5",
-        "@babel/helper-optimise-call-expression": "^7.27.1",
-        "@babel/helper-replace-supers": "^7.28.6",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
-        "@babel/traverse": "^7.28.6",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/@babel/helper-create-regexp-features-plugin": {
-      "version": "7.28.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz",
-      "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.3",
-        "regexpu-core": "^6.3.1",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/@babel/helper-define-polyfill-provider": {
-      "version": "0.6.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz",
-      "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-compilation-targets": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "debug": "^4.4.3",
-        "lodash.debounce": "^4.0.8",
-        "resolve": "^1.22.11"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/@babel/helper-globals": {
-      "version": "7.28.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
-      "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-member-expression-to-functions": {
-      "version": "7.28.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
-      "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/traverse": "^7.28.5",
-        "@babel/types": "^7.28.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-module-imports": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
-      "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/traverse": "^7.28.6",
-        "@babel/types": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-module-transforms": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
-      "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.28.6",
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "@babel/traverse": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-optimise-call-expression": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
-      "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-plugin-utils": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
-      "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-remap-async-to-generator": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz",
-      "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.1",
-        "@babel/helper-wrap-function": "^7.27.1",
-        "@babel/traverse": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-replace-supers": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
-      "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-member-expression-to-functions": "^7.28.5",
-        "@babel/helper-optimise-call-expression": "^7.27.1",
-        "@babel/traverse": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
-      "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/traverse": "^7.27.1",
-        "@babel/types": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-string-parser": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
-      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.28.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
-      "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-validator-option": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
-      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helper-wrap-function": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz",
-      "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/template": "^7.28.6",
-        "@babel/traverse": "^7.28.6",
-        "@babel/types": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/helpers": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
-      "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/template": "^7.28.6",
-        "@babel/types": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/highlight": {
-      "version": "7.25.9",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
-      "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.25.9",
-        "chalk": "^2.4.2",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/parser": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
-      "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.29.0"
-      },
-      "bin": {
-        "parser": "bin/babel-parser.js"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-proposal-decorators": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz",
-      "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/plugin-syntax-decorators": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-proposal-export-default-from": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.27.1.tgz",
-      "integrity": "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-async-generators": {
-      "version": "7.8.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
-      "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-bigint": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
-      "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-class-properties": {
-      "version": "7.12.13",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
-      "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.12.13"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-class-static-block": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
-      "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-decorators": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz",
-      "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-dynamic-import": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
-      "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-export-default-from": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.28.6.tgz",
-      "integrity": "sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-flow": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.28.6.tgz",
-      "integrity": "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-import-attributes": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
-      "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-import-meta": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
-      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-json-strings": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
-      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-jsx": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
-      "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
-      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
-      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-numeric-separator": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
-      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-object-rest-spread": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
-      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
-      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-optional-chaining": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
-      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-private-property-in-object": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
-      "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-top-level-await": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
-      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-syntax-typescript": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
-      "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-arrow-functions": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz",
-      "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-async-generator-functions": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz",
-      "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/helper-remap-async-to-generator": "^7.27.1",
-        "@babel/traverse": "^7.29.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-async-to-generator": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz",
-      "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/helper-remap-async-to-generator": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-block-scoping": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz",
-      "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-class-properties": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz",
-      "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-class-static-block": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz",
-      "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.12.0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-classes": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz",
-      "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.3",
-        "@babel/helper-compilation-targets": "^7.28.6",
-        "@babel/helper-globals": "^7.28.0",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/helper-replace-supers": "^7.28.6",
-        "@babel/traverse": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-computed-properties": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz",
-      "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/template": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-destructuring": {
-      "version": "7.28.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz",
-      "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1",
-        "@babel/traverse": "^7.28.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-export-namespace-from": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz",
-      "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-flow-strip-types": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz",
-      "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1",
-        "@babel/plugin-syntax-flow": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-for-of": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz",
-      "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-function-name": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz",
-      "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-compilation-targets": "^7.27.1",
-        "@babel/helper-plugin-utils": "^7.27.1",
-        "@babel/traverse": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-literals": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz",
-      "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-logical-assignment-operators": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz",
-      "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-modules-commonjs": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz",
-      "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-module-transforms": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz",
-      "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.28.5",
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz",
-      "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-numeric-separator": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz",
-      "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-object-rest-spread": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz",
-      "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-compilation-targets": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/plugin-transform-destructuring": "^7.28.5",
-        "@babel/plugin-transform-parameters": "^7.27.7",
-        "@babel/traverse": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-optional-catch-binding": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz",
-      "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-optional-chaining": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz",
-      "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-parameters": {
-      "version": "7.27.7",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz",
-      "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-private-methods": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz",
-      "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-create-class-features-plugin": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-private-property-in-object": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz",
-      "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.3",
-        "@babel/helper-create-class-features-plugin": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-react-display-name": {
-      "version": "7.28.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz",
-      "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-react-jsx": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz",
-      "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.3",
-        "@babel/helper-module-imports": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/plugin-syntax-jsx": "^7.28.6",
-        "@babel/types": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-react-jsx-development": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz",
-      "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/plugin-transform-react-jsx": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-react-jsx-self": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
-      "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-react-jsx-source": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
-      "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-react-pure-annotations": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz",
-      "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.1",
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-regenerator": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz",
-      "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-runtime": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz",
-      "integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "babel-plugin-polyfill-corejs2": "^0.4.14",
-        "babel-plugin-polyfill-corejs3": "^0.13.0",
-        "babel-plugin-polyfill-regenerator": "^0.6.5",
-        "semver": "^6.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/@babel/plugin-transform-shorthand-properties": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz",
-      "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-spread": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz",
-      "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-sticky-regex": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz",
-      "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-typescript": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.6.tgz",
-      "integrity": "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-annotate-as-pure": "^7.27.3",
-        "@babel/helper-create-class-features-plugin": "^7.28.6",
-        "@babel/helper-plugin-utils": "^7.28.6",
-        "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
-        "@babel/plugin-syntax-typescript": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/plugin-transform-unicode-regex": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz",
-      "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-create-regexp-features-plugin": "^7.27.1",
-        "@babel/helper-plugin-utils": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/preset-react": {
-      "version": "7.28.5",
-      "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz",
-      "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1",
-        "@babel/helper-validator-option": "^7.27.1",
-        "@babel/plugin-transform-react-display-name": "^7.28.0",
-        "@babel/plugin-transform-react-jsx": "^7.27.1",
-        "@babel/plugin-transform-react-jsx-development": "^7.27.1",
-        "@babel/plugin-transform-react-pure-annotations": "^7.27.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/preset-typescript": {
-      "version": "7.28.5",
-      "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz",
-      "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.27.1",
-        "@babel/helper-validator-option": "^7.27.1",
-        "@babel/plugin-syntax-jsx": "^7.27.1",
-        "@babel/plugin-transform-modules-commonjs": "^7.27.1",
-        "@babel/plugin-transform-typescript": "^7.28.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
-      }
-    },
-    "node_modules/@babel/runtime": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
-      "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
-      "license": "MIT",
-      "peer": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/template": {
-      "version": "7.28.6",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
-      "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "^7.28.6",
-        "@babel/parser": "^7.28.6",
-        "@babel/types": "^7.28.6"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/template/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/traverse": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
-      "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "^7.29.0",
-        "@babel/generator": "^7.29.0",
-        "@babel/helper-globals": "^7.28.0",
-        "@babel/parser": "^7.29.0",
-        "@babel/template": "^7.28.6",
-        "@babel/types": "^7.29.0",
-        "debug": "^4.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/traverse--for-generate-function-map": {
-      "name": "@babel/traverse",
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
-      "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "^7.29.0",
-        "@babel/generator": "^7.29.0",
-        "@babel/helper-globals": "^7.28.0",
-        "@babel/parser": "^7.29.0",
-        "@babel/template": "^7.28.6",
-        "@babel/types": "^7.29.0",
-        "debug": "^4.3.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/traverse--for-generate-function-map/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/traverse/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/types": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
-      "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-string-parser": "^7.27.1",
-        "@babel/helper-validator-identifier": "^7.28.5"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@expo/code-signing-certificates": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.6.tgz",
-      "integrity": "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w==",
-      "license": "MIT",
-      "dependencies": {
-        "node-forge": "^1.3.3"
-      }
-    },
-    "node_modules/@expo/config": {
-      "version": "12.0.13",
-      "resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.13.tgz",
-      "integrity": "sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "~7.10.4",
-        "@expo/config-plugins": "~54.0.4",
-        "@expo/config-types": "^54.0.10",
-        "@expo/json-file": "^10.0.8",
-        "deepmerge": "^4.3.1",
-        "getenv": "^2.0.0",
-        "glob": "^13.0.0",
-        "require-from-string": "^2.0.2",
-        "resolve-from": "^5.0.0",
-        "resolve-workspace-root": "^2.0.0",
-        "semver": "^7.6.0",
-        "slugify": "^1.3.4",
-        "sucrase": "~3.35.1"
-      }
-    },
-    "node_modules/@expo/config-plugins": {
-      "version": "54.0.4",
-      "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.4.tgz",
-      "integrity": "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/config-types": "^54.0.10",
-        "@expo/json-file": "~10.0.8",
-        "@expo/plist": "^0.4.8",
-        "@expo/sdk-runtime-versions": "^1.0.0",
-        "chalk": "^4.1.2",
-        "debug": "^4.3.5",
-        "getenv": "^2.0.0",
-        "glob": "^13.0.0",
-        "resolve-from": "^5.0.0",
-        "semver": "^7.5.4",
-        "slash": "^3.0.0",
-        "slugify": "^1.6.6",
-        "xcode": "^3.0.1",
-        "xml2js": "0.6.0"
-      }
-    },
-    "node_modules/@expo/config-plugins/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/config-plugins/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/config-plugins/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/config-plugins/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/config-plugins/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/config-plugins/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/config-types": {
-      "version": "54.0.10",
-      "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.10.tgz",
-      "integrity": "sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/devcert": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.1.tgz",
-      "integrity": "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/sudo-prompt": "^9.3.1",
-        "debug": "^3.1.0"
-      }
-    },
-    "node_modules/@expo/devcert/node_modules/debug": {
-      "version": "3.2.7",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.1"
-      }
-    },
-    "node_modules/@expo/devtools": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-0.1.8.tgz",
-      "integrity": "sha512-SVLxbuanDjJPgc0sy3EfXUMLb/tXzp6XIHkhtPVmTWJAp+FOr6+5SeiCfJrCzZFet0Ifyke2vX3sFcKwEvCXwQ==",
-      "license": "MIT",
-      "dependencies": {
-        "chalk": "^4.1.2"
-      },
-      "peerDependencies": {
-        "react": "*",
-        "react-native": "*"
-      },
-      "peerDependenciesMeta": {
-        "react": {
-          "optional": true
-        },
-        "react-native": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@expo/devtools/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/devtools/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/devtools/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/devtools/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/devtools/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/devtools/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/env": {
-      "version": "2.0.8",
-      "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.0.8.tgz",
-      "integrity": "sha512-5VQD6GT8HIMRaSaB5JFtOXuvfDVU80YtZIuUT/GDhUF782usIXY13Tn3IdDz1Tm/lqA9qnRZQ1BF4t7LlvdJPA==",
-      "license": "MIT",
-      "dependencies": {
-        "chalk": "^4.0.0",
-        "debug": "^4.3.4",
-        "dotenv": "~16.4.5",
-        "dotenv-expand": "~11.0.6",
-        "getenv": "^2.0.0"
-      }
-    },
-    "node_modules/@expo/env/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/env/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/env/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/env/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/env/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/env/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/fingerprint": {
-      "version": "0.15.4",
-      "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.15.4.tgz",
-      "integrity": "sha512-eYlxcrGdR2/j2M6pEDXo9zU9KXXF1vhP+V+Tl+lyY+bU8lnzrN6c637mz6Ye3em2ANy8hhUR03Raf8VsT9Ogng==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/spawn-async": "^1.7.2",
-        "arg": "^5.0.2",
-        "chalk": "^4.1.2",
-        "debug": "^4.3.4",
-        "getenv": "^2.0.0",
-        "glob": "^13.0.0",
-        "ignore": "^5.3.1",
-        "minimatch": "^9.0.0",
-        "p-limit": "^3.1.0",
-        "resolve-from": "^5.0.0",
-        "semver": "^7.6.0"
-      },
-      "bin": {
-        "fingerprint": "bin/cli.js"
-      }
-    },
-    "node_modules/@expo/fingerprint/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/fingerprint/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/fingerprint/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/fingerprint/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/fingerprint/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/fingerprint/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/image-utils": {
-      "version": "0.8.8",
-      "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.8.8.tgz",
-      "integrity": "sha512-HHHaG4J4nKjTtVa1GG9PCh763xlETScfEyNxxOvfTRr8IKPJckjTyqSLEtdJoFNJ1vqiABEjW7tqGhqGibZLeA==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/spawn-async": "^1.7.2",
-        "chalk": "^4.0.0",
-        "getenv": "^2.0.0",
-        "jimp-compact": "0.16.1",
-        "parse-png": "^2.1.0",
-        "resolve-from": "^5.0.0",
-        "resolve-global": "^1.0.0",
-        "semver": "^7.6.0",
-        "temp-dir": "~2.0.0",
-        "unique-string": "~2.0.0"
-      }
-    },
-    "node_modules/@expo/image-utils/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/image-utils/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/image-utils/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/image-utils/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/image-utils/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/image-utils/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/json-file": {
-      "version": "10.0.8",
-      "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-10.0.8.tgz",
-      "integrity": "sha512-9LOTh1PgKizD1VXfGQ88LtDH0lRwq9lsTb4aichWTWSWqy3Ugfkhfm3BhzBIkJJfQQ5iJu3m/BoRlEIjoCGcnQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "~7.10.4",
-        "json5": "^2.2.3"
-      }
-    },
-    "node_modules/@expo/metro": {
-      "version": "54.2.0",
-      "resolved": "https://registry.npmjs.org/@expo/metro/-/metro-54.2.0.tgz",
-      "integrity": "sha512-h68TNZPGsk6swMmLm9nRSnE2UXm48rWwgcbtAHVMikXvbxdS41NDHHeqg1rcQ9AbznDRp6SQVC2MVpDnsRKU1w==",
-      "license": "MIT",
-      "dependencies": {
-        "metro": "0.83.3",
-        "metro-babel-transformer": "0.83.3",
-        "metro-cache": "0.83.3",
-        "metro-cache-key": "0.83.3",
-        "metro-config": "0.83.3",
-        "metro-core": "0.83.3",
-        "metro-file-map": "0.83.3",
-        "metro-minify-terser": "0.83.3",
-        "metro-resolver": "0.83.3",
-        "metro-runtime": "0.83.3",
-        "metro-source-map": "0.83.3",
-        "metro-symbolicate": "0.83.3",
-        "metro-transform-plugins": "0.83.3",
-        "metro-transform-worker": "0.83.3"
-      }
-    },
-    "node_modules/@expo/osascript": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.3.8.tgz",
-      "integrity": "sha512-/TuOZvSG7Nn0I8c+FcEaoHeBO07yu6vwDgk7rZVvAXoeAK5rkA09jRyjYsZo+0tMEFaToBeywA6pj50Mb3ny9w==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/spawn-async": "^1.7.2",
-        "exec-async": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@expo/package-manager": {
-      "version": "1.9.10",
-      "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.9.10.tgz",
-      "integrity": "sha512-axJm+NOj3jVxep49va/+L3KkF3YW/dkV+RwzqUJedZrv4LeTqOG4rhrCaCPXHTvLqCTDKu6j0Xyd28N7mnxsGA==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/json-file": "^10.0.8",
-        "@expo/spawn-async": "^1.7.2",
-        "chalk": "^4.0.0",
-        "npm-package-arg": "^11.0.0",
-        "ora": "^3.4.0",
-        "resolve-workspace-root": "^2.0.0"
-      }
-    },
-    "node_modules/@expo/package-manager/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/package-manager/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/package-manager/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/package-manager/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/package-manager/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/package-manager/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/plist": {
-      "version": "0.4.8",
-      "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.4.8.tgz",
-      "integrity": "sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@xmldom/xmldom": "^0.8.8",
-        "base64-js": "^1.2.3",
-        "xmlbuilder": "^15.1.1"
-      }
-    },
-    "node_modules/@expo/schema-utils": {
-      "version": "0.1.8",
-      "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-0.1.8.tgz",
-      "integrity": "sha512-9I6ZqvnAvKKDiO+ZF8BpQQFYWXOJvTAL5L/227RUbWG1OVZDInFifzCBiqAZ3b67NRfeAgpgvbA7rejsqhY62A==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/sdk-runtime-versions": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz",
-      "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/spawn-async": {
-      "version": "1.7.2",
-      "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.7.2.tgz",
-      "integrity": "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==",
-      "license": "MIT",
-      "dependencies": {
-        "cross-spawn": "^7.0.3"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@expo/sudo-prompt": {
-      "version": "9.3.2",
-      "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz",
-      "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/ws-tunnel": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-1.0.6.tgz",
-      "integrity": "sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/xcpretty": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.4.0.tgz",
-      "integrity": "sha512-o2qDlTqJ606h4xR36H2zWTywmZ3v3842K6TU8Ik2n1mfW0S580VHlt3eItVYdLYz+klaPp7CXqanja8eASZjRw==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@babel/code-frame": "^7.20.0",
-        "chalk": "^4.1.0",
-        "js-yaml": "^4.1.0"
-      },
-      "bin": {
-        "excpretty": "build/cli.js"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "license": "Python-2.0"
-    },
-    "node_modules/@expo/xcpretty/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@expo/xcpretty/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/js-yaml": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
-      "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
-      "license": "MIT",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/@expo/xcpretty/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@isaacs/balanced-match": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
-      "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
-      "license": "MIT",
-      "engines": {
-        "node": "20 || >=22"
-      }
-    },
-    "node_modules/@isaacs/brace-expansion": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz",
-      "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@isaacs/balanced-match": "^4.0.1"
-      },
-      "engines": {
-        "node": "20 || >=22"
-      }
-    },
-    "node_modules/@isaacs/fs-minipass": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
-      "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
-      "license": "ISC",
-      "dependencies": {
-        "minipass": "^7.0.4"
-      },
-      "engines": {
-        "node": ">=18.0.0"
-      }
-    },
-    "node_modules/@isaacs/ttlcache": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
-      "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@istanbuljs/load-nyc-config": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
-      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
-      "license": "ISC",
-      "dependencies": {
-        "camelcase": "^5.3.1",
-        "find-up": "^4.1.0",
-        "get-package-type": "^0.1.0",
-        "js-yaml": "^3.13.1",
-        "resolve-from": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@istanbuljs/schema": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
-      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@jest/create-cache-key-function": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
-      "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/types": "^29.6.3"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/@jest/environment": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
-      "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/fake-timers": "^29.7.0",
-        "@jest/types": "^29.6.3",
-        "@types/node": "*",
-        "jest-mock": "^29.7.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/@jest/fake-timers": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
-      "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/types": "^29.6.3",
-        "@sinonjs/fake-timers": "^10.0.2",
-        "@types/node": "*",
-        "jest-message-util": "^29.7.0",
-        "jest-mock": "^29.7.0",
-        "jest-util": "^29.7.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/@jest/schemas": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
-      "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
-      "license": "MIT",
-      "dependencies": {
-        "@sinclair/typebox": "^0.27.8"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/@jest/transform": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
-      "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/core": "^7.11.6",
-        "@jest/types": "^29.6.3",
-        "@jridgewell/trace-mapping": "^0.3.18",
-        "babel-plugin-istanbul": "^6.1.1",
-        "chalk": "^4.0.0",
-        "convert-source-map": "^2.0.0",
-        "fast-json-stable-stringify": "^2.1.0",
-        "graceful-fs": "^4.2.9",
-        "jest-haste-map": "^29.7.0",
-        "jest-regex-util": "^29.6.3",
-        "jest-util": "^29.7.0",
-        "micromatch": "^4.0.4",
-        "pirates": "^4.0.4",
-        "slash": "^3.0.0",
-        "write-file-atomic": "^4.0.2"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/@jest/transform/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@jest/transform/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@jest/transform/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@jest/transform/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@jest/transform/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@jest/transform/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@jest/types": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
-      "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/schemas": "^29.6.3",
-        "@types/istanbul-lib-coverage": "^2.0.0",
-        "@types/istanbul-reports": "^3.0.0",
-        "@types/node": "*",
-        "@types/yargs": "^17.0.8",
-        "chalk": "^4.0.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/@jest/types/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/@jest/types/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@jest/types/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/@jest/types/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/@jest/types/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@jest/types/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/@jridgewell/gen-mapping": {
-      "version": "0.3.13",
-      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
-      "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/sourcemap-codec": "^1.5.0",
-        "@jridgewell/trace-mapping": "^0.3.24"
-      }
-    },
-    "node_modules/@jridgewell/remapping": {
-      "version": "2.3.5",
-      "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
-      "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.5",
-        "@jridgewell/trace-mapping": "^0.3.24"
-      }
-    },
-    "node_modules/@jridgewell/resolve-uri": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
-      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/source-map": {
-      "version": "0.3.11",
-      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
-      "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.5",
-        "@jridgewell/trace-mapping": "^0.3.25"
-      }
-    },
-    "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.5.5",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
-      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
-      "license": "MIT"
-    },
-    "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.31",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
-      "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/resolve-uri": "^3.1.0",
-        "@jridgewell/sourcemap-codec": "^1.4.14"
-      }
-    },
-    "node_modules/@react-native/assets-registry": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz",
-      "integrity": "sha512-705B6x/5Kxm1RKRvSv0ADYWm5JOnoiQ1ufW7h8uu2E6G9Of/eE6hP/Ivw3U5jI16ERqZxiKQwk34VJbB0niX9w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 20.19.4"
-      }
-    },
-    "node_modules/@react-native/babel-plugin-codegen": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz",
-      "integrity": "sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/traverse": "^7.25.3",
-        "@react-native/codegen": "0.81.5"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      }
-    },
-    "node_modules/@react-native/babel-preset": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.81.5.tgz",
-      "integrity": "sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/core": "^7.25.2",
-        "@babel/plugin-proposal-export-default-from": "^7.24.7",
-        "@babel/plugin-syntax-dynamic-import": "^7.8.3",
-        "@babel/plugin-syntax-export-default-from": "^7.24.7",
-        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
-        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
-        "@babel/plugin-transform-arrow-functions": "^7.24.7",
-        "@babel/plugin-transform-async-generator-functions": "^7.25.4",
-        "@babel/plugin-transform-async-to-generator": "^7.24.7",
-        "@babel/plugin-transform-block-scoping": "^7.25.0",
-        "@babel/plugin-transform-class-properties": "^7.25.4",
-        "@babel/plugin-transform-classes": "^7.25.4",
-        "@babel/plugin-transform-computed-properties": "^7.24.7",
-        "@babel/plugin-transform-destructuring": "^7.24.8",
-        "@babel/plugin-transform-flow-strip-types": "^7.25.2",
-        "@babel/plugin-transform-for-of": "^7.24.7",
-        "@babel/plugin-transform-function-name": "^7.25.1",
-        "@babel/plugin-transform-literals": "^7.25.2",
-        "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
-        "@babel/plugin-transform-modules-commonjs": "^7.24.8",
-        "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
-        "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
-        "@babel/plugin-transform-numeric-separator": "^7.24.7",
-        "@babel/plugin-transform-object-rest-spread": "^7.24.7",
-        "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
-        "@babel/plugin-transform-optional-chaining": "^7.24.8",
-        "@babel/plugin-transform-parameters": "^7.24.7",
-        "@babel/plugin-transform-private-methods": "^7.24.7",
-        "@babel/plugin-transform-private-property-in-object": "^7.24.7",
-        "@babel/plugin-transform-react-display-name": "^7.24.7",
-        "@babel/plugin-transform-react-jsx": "^7.25.2",
-        "@babel/plugin-transform-react-jsx-self": "^7.24.7",
-        "@babel/plugin-transform-react-jsx-source": "^7.24.7",
-        "@babel/plugin-transform-regenerator": "^7.24.7",
-        "@babel/plugin-transform-runtime": "^7.24.7",
-        "@babel/plugin-transform-shorthand-properties": "^7.24.7",
-        "@babel/plugin-transform-spread": "^7.24.7",
-        "@babel/plugin-transform-sticky-regex": "^7.24.7",
-        "@babel/plugin-transform-typescript": "^7.25.2",
-        "@babel/plugin-transform-unicode-regex": "^7.24.7",
-        "@babel/template": "^7.25.0",
-        "@react-native/babel-plugin-codegen": "0.81.5",
-        "babel-plugin-syntax-hermes-parser": "0.29.1",
-        "babel-plugin-transform-flow-enums": "^0.0.2",
-        "react-refresh": "^0.14.0"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "*"
-      }
-    },
-    "node_modules/@react-native/codegen": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.5.tgz",
-      "integrity": "sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/core": "^7.25.2",
-        "@babel/parser": "^7.25.3",
-        "glob": "^7.1.1",
-        "hermes-parser": "0.29.1",
-        "invariant": "^2.2.4",
-        "nullthrows": "^1.1.1",
-        "yargs": "^17.6.2"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "*"
-      }
-    },
-    "node_modules/@react-native/codegen/node_modules/brace-expansion": {
-      "version": "1.1.12",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
-      "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/@react-native/codegen/node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
-      "license": "ISC",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/@react-native/codegen/node_modules/hermes-estree": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
-      "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
-      "license": "MIT"
-    },
-    "node_modules/@react-native/codegen/node_modules/hermes-parser": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
-      "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
-      "license": "MIT",
-      "dependencies": {
-        "hermes-estree": "0.29.1"
-      }
-    },
-    "node_modules/@react-native/codegen/node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/@react-native/community-cli-plugin": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.5.tgz",
-      "integrity": "sha512-yWRlmEOtcyvSZ4+OvqPabt+NS36vg0K/WADTQLhrYrm9qdZSuXmq8PmdJWz/68wAqKQ+4KTILiq2kjRQwnyhQw==",
-      "license": "MIT",
-      "dependencies": {
-        "@react-native/dev-middleware": "0.81.5",
-        "debug": "^4.4.0",
-        "invariant": "^2.2.4",
-        "metro": "^0.83.1",
-        "metro-config": "^0.83.1",
-        "metro-core": "^0.83.1",
-        "semver": "^7.1.3"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      },
-      "peerDependencies": {
-        "@react-native-community/cli": "*",
-        "@react-native/metro-config": "*"
-      },
-      "peerDependenciesMeta": {
-        "@react-native-community/cli": {
-          "optional": true
-        },
-        "@react-native/metro-config": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@react-native/debugger-frontend": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz",
-      "integrity": "sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==",
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">= 20.19.4"
-      }
-    },
-    "node_modules/@react-native/dev-middleware": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz",
-      "integrity": "sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==",
-      "license": "MIT",
-      "dependencies": {
-        "@isaacs/ttlcache": "^1.4.1",
-        "@react-native/debugger-frontend": "0.81.5",
-        "chrome-launcher": "^0.15.2",
-        "chromium-edge-launcher": "^0.2.0",
-        "connect": "^3.6.5",
-        "debug": "^4.4.0",
-        "invariant": "^2.2.4",
-        "nullthrows": "^1.1.1",
-        "open": "^7.0.3",
-        "serve-static": "^1.16.2",
-        "ws": "^6.2.3"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      }
-    },
-    "node_modules/@react-native/dev-middleware/node_modules/ws": {
-      "version": "6.2.3",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
-      "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
-      "license": "MIT",
-      "dependencies": {
-        "async-limiter": "~1.0.0"
-      }
-    },
-    "node_modules/@react-native/gradle-plugin": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.81.5.tgz",
-      "integrity": "sha512-hORRlNBj+ReNMLo9jme3yQ6JQf4GZpVEBLxmTXGGlIL78MAezDZr5/uq9dwElSbcGmLEgeiax6e174Fie6qPLg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 20.19.4"
-      }
-    },
-    "node_modules/@react-native/js-polyfills": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.81.5.tgz",
-      "integrity": "sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 20.19.4"
-      }
-    },
-    "node_modules/@react-native/normalize-colors": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz",
-      "integrity": "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==",
-      "license": "MIT"
-    },
-    "node_modules/@sinclair/typebox": {
-      "version": "0.27.10",
-      "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
-      "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
-      "license": "MIT"
-    },
-    "node_modules/@sinonjs/commons": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
-      "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "type-detect": "4.0.8"
-      }
-    },
-    "node_modules/@sinonjs/fake-timers": {
-      "version": "10.3.0",
-      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
-      "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@sinonjs/commons": "^3.0.0"
-      }
-    },
-    "node_modules/@types/babel__core": {
-      "version": "7.20.5",
-      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
-      "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/parser": "^7.20.7",
-        "@babel/types": "^7.20.7",
-        "@types/babel__generator": "*",
-        "@types/babel__template": "*",
-        "@types/babel__traverse": "*"
-      }
-    },
-    "node_modules/@types/babel__generator": {
-      "version": "7.27.0",
-      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
-      "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.0.0"
-      }
-    },
-    "node_modules/@types/babel__template": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
-      "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/parser": "^7.1.0",
-        "@babel/types": "^7.0.0"
-      }
-    },
-    "node_modules/@types/babel__traverse": {
-      "version": "7.28.0",
-      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
-      "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.28.2"
-      }
-    },
-    "node_modules/@types/graceful-fs": {
-      "version": "4.1.9",
-      "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
-      "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/istanbul-lib-coverage": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
-      "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
-      "license": "MIT"
-    },
-    "node_modules/@types/istanbul-lib-report": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
-      "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/istanbul-lib-coverage": "*"
-      }
-    },
-    "node_modules/@types/istanbul-reports": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
-      "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/istanbul-lib-report": "*"
-      }
-    },
-    "node_modules/@types/node": {
-      "version": "25.2.2",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.2.tgz",
-      "integrity": "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ==",
-      "license": "MIT",
-      "dependencies": {
-        "undici-types": "~7.16.0"
-      }
-    },
-    "node_modules/@types/react": {
-      "version": "19.1.17",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.17.tgz",
-      "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==",
-      "devOptional": true,
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "csstype": "^3.0.2"
-      }
-    },
-    "node_modules/@types/stack-utils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
-      "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
-      "license": "MIT"
-    },
-    "node_modules/@types/yargs": {
-      "version": "17.0.35",
-      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
-      "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/yargs-parser": "*"
-      }
-    },
-    "node_modules/@types/yargs-parser": {
-      "version": "21.0.3",
-      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
-      "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
-      "license": "MIT"
-    },
-    "node_modules/@ungap/structured-clone": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
-      "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
-      "license": "ISC"
-    },
-    "node_modules/@urql/core": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@urql/core/-/core-5.2.0.tgz",
-      "integrity": "sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A==",
-      "license": "MIT",
-      "dependencies": {
-        "@0no-co/graphql.web": "^1.0.13",
-        "wonka": "^6.3.2"
-      }
-    },
-    "node_modules/@urql/exchange-retry": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-1.3.2.tgz",
-      "integrity": "sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg==",
-      "license": "MIT",
-      "dependencies": {
-        "@urql/core": "^5.1.2",
-        "wonka": "^6.3.2"
-      },
-      "peerDependencies": {
-        "@urql/core": "^5.0.0"
-      }
-    },
-    "node_modules/@xmldom/xmldom": {
-      "version": "0.8.11",
-      "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz",
-      "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/abort-controller": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
-      "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
-      "license": "MIT",
-      "dependencies": {
-        "event-target-shim": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=6.5"
-      }
-    },
-    "node_modules/accepts": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
-      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-      "license": "MIT",
-      "dependencies": {
-        "mime-types": "~2.1.34",
-        "negotiator": "0.6.3"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/acorn": {
-      "version": "8.15.0",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-      "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
-      "license": "MIT",
-      "bin": {
-        "acorn": "bin/acorn"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/agent-base": {
-      "version": "7.1.4",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
-      "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/anser": {
-      "version": "1.4.10",
-      "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz",
-      "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
-      "license": "MIT"
-    },
-    "node_modules/ansi-escapes": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
-      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
-      "license": "MIT",
-      "dependencies": {
-        "type-fest": "^0.21.3"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ansi-escapes/node_modules/type-fest": {
-      "version": "0.21.3",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
-      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
-      "license": "(MIT OR CC0-1.0)",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/any-promise": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
-      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
-      "license": "MIT"
-    },
-    "node_modules/anymatch": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-      "license": "ISC",
-      "dependencies": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/arg": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
-      "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
-      "license": "MIT"
-    },
-    "node_modules/argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "license": "MIT",
-      "dependencies": {
-        "sprintf-js": "~1.0.2"
-      }
-    },
-    "node_modules/asap": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
-      "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
-      "license": "MIT"
-    },
-    "node_modules/async-limiter": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
-      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
-      "license": "MIT"
-    },
-    "node_modules/babel-jest": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
-      "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/transform": "^29.7.0",
-        "@types/babel__core": "^7.1.14",
-        "babel-plugin-istanbul": "^6.1.1",
-        "babel-preset-jest": "^29.6.3",
-        "chalk": "^4.0.0",
-        "graceful-fs": "^4.2.9",
-        "slash": "^3.0.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.8.0"
-      }
-    },
-    "node_modules/babel-jest/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/babel-jest/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/babel-jest/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/babel-jest/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/babel-jest/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/babel-jest/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/babel-plugin-istanbul": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
-      "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.0.0",
-        "@istanbuljs/load-nyc-config": "^1.0.0",
-        "@istanbuljs/schema": "^0.1.2",
-        "istanbul-lib-instrument": "^5.0.4",
-        "test-exclude": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/babel-plugin-jest-hoist": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
-      "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/template": "^7.3.3",
-        "@babel/types": "^7.3.3",
-        "@types/babel__core": "^7.1.14",
-        "@types/babel__traverse": "^7.0.6"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-corejs2": {
-      "version": "0.4.15",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz",
-      "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/compat-data": "^7.28.6",
-        "@babel/helper-define-polyfill-provider": "^0.6.6",
-        "semver": "^6.3.1"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-corejs3": {
-      "version": "0.13.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz",
-      "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-define-polyfill-provider": "^0.6.5",
-        "core-js-compat": "^3.43.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/babel-plugin-polyfill-regenerator": {
-      "version": "0.6.6",
-      "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz",
-      "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-define-polyfill-provider": "^0.6.6"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
-      }
-    },
-    "node_modules/babel-plugin-react-compiler": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz",
-      "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/types": "^7.26.0"
-      }
-    },
-    "node_modules/babel-plugin-react-native-web": {
-      "version": "0.21.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz",
-      "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==",
-      "license": "MIT"
-    },
-    "node_modules/babel-plugin-syntax-hermes-parser": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz",
-      "integrity": "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==",
-      "license": "MIT",
-      "dependencies": {
-        "hermes-parser": "0.29.1"
-      }
-    },
-    "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-estree": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
-      "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
-      "license": "MIT"
-    },
-    "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
-      "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
-      "license": "MIT",
-      "dependencies": {
-        "hermes-estree": "0.29.1"
-      }
-    },
-    "node_modules/babel-plugin-transform-flow-enums": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz",
-      "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/plugin-syntax-flow": "^7.12.1"
-      }
-    },
-    "node_modules/babel-preset-current-node-syntax": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
-      "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/plugin-syntax-async-generators": "^7.8.4",
-        "@babel/plugin-syntax-bigint": "^7.8.3",
-        "@babel/plugin-syntax-class-properties": "^7.12.13",
-        "@babel/plugin-syntax-class-static-block": "^7.14.5",
-        "@babel/plugin-syntax-import-attributes": "^7.24.7",
-        "@babel/plugin-syntax-import-meta": "^7.10.4",
-        "@babel/plugin-syntax-json-strings": "^7.8.3",
-        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
-        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
-        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
-        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
-        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
-        "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
-        "@babel/plugin-syntax-top-level-await": "^7.14.5"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0 || ^8.0.0-0"
-      }
-    },
-    "node_modules/babel-preset-jest": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
-      "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
-      "license": "MIT",
-      "dependencies": {
-        "babel-plugin-jest-hoist": "^29.6.3",
-        "babel-preset-current-node-syntax": "^1.0.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0"
-      }
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "license": "MIT"
-    },
-    "node_modules/base64-js": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/baseline-browser-mapping": {
-      "version": "2.9.19",
-      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
-      "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
-      "license": "Apache-2.0",
-      "bin": {
-        "baseline-browser-mapping": "dist/cli.js"
-      }
-    },
-    "node_modules/better-opn": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz",
-      "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==",
-      "license": "MIT",
-      "dependencies": {
-        "open": "^8.0.4"
-      },
-      "engines": {
-        "node": ">=12.0.0"
-      }
-    },
-    "node_modules/better-opn/node_modules/open": {
-      "version": "8.4.2",
-      "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
-      "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
-      "license": "MIT",
-      "dependencies": {
-        "define-lazy-prop": "^2.0.0",
-        "is-docker": "^2.1.1",
-        "is-wsl": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/big-integer": {
-      "version": "1.6.52",
-      "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
-      "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
-      "license": "Unlicense",
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
-    "node_modules/bplist-creator": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz",
-      "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==",
-      "license": "MIT",
-      "dependencies": {
-        "stream-buffers": "2.2.x"
-      }
-    },
-    "node_modules/bplist-parser": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
-      "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
-      "license": "MIT",
-      "dependencies": {
-        "big-integer": "1.6.x"
-      },
-      "engines": {
-        "node": ">= 5.10.0"
-      }
-    },
-    "node_modules/brace-expansion": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
-      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0"
-      }
-    },
-    "node_modules/braces": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
-      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "license": "MIT",
-      "dependencies": {
-        "fill-range": "^7.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/browserslist": {
-      "version": "4.28.1",
-      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
-      "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/browserslist"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "baseline-browser-mapping": "^2.9.0",
-        "caniuse-lite": "^1.0.30001759",
-        "electron-to-chromium": "^1.5.263",
-        "node-releases": "^2.0.27",
-        "update-browserslist-db": "^1.2.0"
-      },
-      "bin": {
-        "browserslist": "cli.js"
-      },
-      "engines": {
-        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-      }
-    },
-    "node_modules/bser": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
-      "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "node-int64": "^0.4.0"
-      }
-    },
-    "node_modules/buffer": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "base64-js": "^1.3.1",
-        "ieee754": "^1.1.13"
-      }
-    },
-    "node_modules/buffer-from": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
-      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
-      "license": "MIT"
-    },
-    "node_modules/bytes": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/camelcase": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
-      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/caniuse-lite": {
-      "version": "1.0.30001769",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz",
-      "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==",
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "CC-BY-4.0"
-    },
-    "node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/chownr": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
-      "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
-      "license": "BlueOak-1.0.0",
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/chrome-launcher": {
-      "version": "0.15.2",
-      "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
-      "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@types/node": "*",
-        "escape-string-regexp": "^4.0.0",
-        "is-wsl": "^2.2.0",
-        "lighthouse-logger": "^1.0.0"
-      },
-      "bin": {
-        "print-chrome-path": "bin/print-chrome-path.js"
-      },
-      "engines": {
-        "node": ">=12.13.0"
-      }
-    },
-    "node_modules/chrome-launcher/node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/chromium-edge-launcher": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz",
-      "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@types/node": "*",
-        "escape-string-regexp": "^4.0.0",
-        "is-wsl": "^2.2.0",
-        "lighthouse-logger": "^1.0.0",
-        "mkdirp": "^1.0.4",
-        "rimraf": "^3.0.2"
-      }
-    },
-    "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ci-info": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
-      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
-      "license": "MIT"
-    },
-    "node_modules/cli-cursor": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
-      "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
-      "license": "MIT",
-      "dependencies": {
-        "restore-cursor": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/cli-spinners": {
-      "version": "2.9.2",
-      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
-      "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/cliui": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
-      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
-      "license": "ISC",
-      "dependencies": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.1",
-        "wrap-ansi": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/clone": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-      "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "license": "MIT"
-    },
-    "node_modules/commander": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
-      "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/compressible": {
-      "version": "2.0.18",
-      "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
-      "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
-      "license": "MIT",
-      "dependencies": {
-        "mime-db": ">= 1.43.0 < 2"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/compression": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
-      "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
-      "license": "MIT",
-      "dependencies": {
-        "bytes": "3.1.2",
-        "compressible": "~2.0.18",
-        "debug": "2.6.9",
-        "negotiator": "~0.6.4",
-        "on-headers": "~1.1.0",
-        "safe-buffer": "5.2.1",
-        "vary": "~1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/compression/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/compression/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "license": "MIT"
-    },
-    "node_modules/compression/node_modules/negotiator": {
-      "version": "0.6.4",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
-      "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "license": "MIT"
-    },
-    "node_modules/connect": {
-      "version": "3.7.0",
-      "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
-      "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "2.6.9",
-        "finalhandler": "1.1.2",
-        "parseurl": "~1.3.3",
-        "utils-merge": "1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/connect/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/connect/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "license": "MIT"
-    },
-    "node_modules/convert-source-map": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
-      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
-      "license": "MIT"
-    },
-    "node_modules/core-js-compat": {
-      "version": "3.48.0",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz",
-      "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==",
-      "license": "MIT",
-      "dependencies": {
-        "browserslist": "^4.28.1"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/core-js"
-      }
-    },
-    "node_modules/cross-spawn": {
-      "version": "7.0.6",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
-      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
-      "license": "MIT",
-      "dependencies": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/crypto-random-string": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
-      "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/csstype": {
-      "version": "3.2.3",
-      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
-      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
-      "devOptional": true,
-      "license": "MIT"
-    },
-    "node_modules/debug": {
-      "version": "4.4.3",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
-      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/deep-extend": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
-      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/deepmerge": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
-      "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/defaults": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
-      "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
-      "license": "MIT",
-      "dependencies": {
-        "clone": "^1.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/define-lazy-prop": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
-      "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/depd": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/destroy": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
-      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8",
-        "npm": "1.2.8000 || >= 1.4.16"
-      }
-    },
-    "node_modules/detect-libc": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
-      "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
-      "license": "Apache-2.0",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/dotenv": {
-      "version": "16.4.7",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
-      "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://dotenvx.com"
-      }
-    },
-    "node_modules/dotenv-expand": {
-      "version": "11.0.7",
-      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz",
-      "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==",
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "dotenv": "^16.4.5"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://dotenvx.com"
-      }
-    },
-    "node_modules/ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
-      "license": "MIT"
-    },
-    "node_modules/electron-to-chromium": {
-      "version": "1.5.286",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz",
-      "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==",
-      "license": "ISC"
-    },
-    "node_modules/emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-      "license": "MIT"
-    },
-    "node_modules/encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/env-editor": {
-      "version": "0.4.2",
-      "resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz",
-      "integrity": "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/error-stack-parser": {
-      "version": "2.1.4",
-      "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
-      "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
-      "license": "MIT",
-      "dependencies": {
-        "stackframe": "^1.3.4"
-      }
-    },
-    "node_modules/escalade": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
-      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
-      "license": "MIT"
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/esprima": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-      "license": "BSD-2-Clause",
-      "bin": {
-        "esparse": "bin/esparse.js",
-        "esvalidate": "bin/esvalidate.js"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/event-target-shim": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
-      "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/exec-async": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/exec-async/-/exec-async-2.2.0.tgz",
-      "integrity": "sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw==",
-      "license": "MIT"
-    },
-    "node_modules/expo": {
-      "version": "54.0.33",
-      "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz",
-      "integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==",
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "@babel/runtime": "^7.20.0",
-        "@expo/cli": "54.0.23",
-        "@expo/config": "~12.0.13",
-        "@expo/config-plugins": "~54.0.4",
-        "@expo/devtools": "0.1.8",
-        "@expo/fingerprint": "0.15.4",
-        "@expo/metro": "~54.2.0",
-        "@expo/metro-config": "54.0.14",
-        "@expo/vector-icons": "^15.0.3",
-        "@ungap/structured-clone": "^1.3.0",
-        "babel-preset-expo": "~54.0.10",
-        "expo-asset": "~12.0.12",
-        "expo-constants": "~18.0.13",
-        "expo-file-system": "~19.0.21",
-        "expo-font": "~14.0.11",
-        "expo-keep-awake": "~15.0.8",
-        "expo-modules-autolinking": "3.0.24",
-        "expo-modules-core": "3.0.29",
-        "pretty-format": "^29.7.0",
-        "react-refresh": "^0.14.2",
-        "whatwg-url-without-unicode": "8.0.0-3"
-      },
-      "bin": {
-        "expo": "bin/cli",
-        "expo-modules-autolinking": "bin/autolinking",
-        "fingerprint": "bin/fingerprint"
-      },
-      "peerDependencies": {
-        "@expo/dom-webview": "*",
-        "@expo/metro-runtime": "*",
-        "react": "*",
-        "react-native": "*",
-        "react-native-webview": "*"
-      },
-      "peerDependenciesMeta": {
-        "@expo/dom-webview": {
-          "optional": true
-        },
-        "@expo/metro-runtime": {
-          "optional": true
-        },
-        "react-native-webview": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/expo-modules-autolinking": {
-      "version": "3.0.24",
-      "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.24.tgz",
-      "integrity": "sha512-TP+6HTwhL7orDvsz2VzauyQlXJcAWyU3ANsZ7JGL4DQu8XaZv/A41ZchbtAYLfozNA2Ya1Hzmhx65hXryBMjaQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/spawn-async": "^1.7.2",
-        "chalk": "^4.1.0",
-        "commander": "^7.2.0",
-        "require-from-string": "^2.0.2",
-        "resolve-from": "^5.0.0"
-      },
-      "bin": {
-        "expo-modules-autolinking": "bin/expo-modules-autolinking.js"
-      }
-    },
-    "node_modules/expo-modules-autolinking/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/expo-modules-autolinking/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/expo-modules-autolinking/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/expo-modules-autolinking/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/expo-modules-autolinking/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/expo-modules-autolinking/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/expo-modules-core": {
-      "version": "3.0.29",
-      "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-3.0.29.tgz",
-      "integrity": "sha512-LzipcjGqk8gvkrOUf7O2mejNWugPkf3lmd9GkqL9WuNyeN2fRwU0Dn77e3ZUKI3k6sI+DNwjkq4Nu9fNN9WS7Q==",
-      "license": "MIT",
-      "dependencies": {
-        "invariant": "^2.2.4"
-      },
-      "peerDependencies": {
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo-server": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-1.0.5.tgz",
-      "integrity": "sha512-IGR++flYH70rhLyeXF0Phle56/k4cee87WeQ4mamS+MkVAVP+dDlOHf2nN06Z9Y2KhU0Gp1k+y61KkghF7HdhA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=20.16.0"
-      }
-    },
-    "node_modules/expo-status-bar": {
-      "version": "3.0.9",
-      "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-3.0.9.tgz",
-      "integrity": "sha512-xyYyVg6V1/SSOZWh4Ni3U129XHCnFHBTcUo0dhWtFDrZbNp/duw5AGsQfb2sVeU0gxWHXSY1+5F0jnKYC7WuOw==",
-      "license": "MIT",
-      "dependencies": {
-        "react-native-is-edge-to-edge": "^1.2.1"
-      },
-      "peerDependencies": {
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/expo/node_modules/@expo/cli": {
-      "version": "54.0.23",
-      "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-54.0.23.tgz",
-      "integrity": "sha512-km0h72SFfQCmVycH/JtPFTVy69w6Lx1cHNDmfLfQqgKFYeeHTjx7LVDP4POHCtNxFP2UeRazrygJhlh4zz498g==",
-      "license": "MIT",
-      "dependencies": {
-        "@0no-co/graphql.web": "^1.0.8",
-        "@expo/code-signing-certificates": "^0.0.6",
-        "@expo/config": "~12.0.13",
-        "@expo/config-plugins": "~54.0.4",
-        "@expo/devcert": "^1.2.1",
-        "@expo/env": "~2.0.8",
-        "@expo/image-utils": "^0.8.8",
-        "@expo/json-file": "^10.0.8",
-        "@expo/metro": "~54.2.0",
-        "@expo/metro-config": "~54.0.14",
-        "@expo/osascript": "^2.3.8",
-        "@expo/package-manager": "^1.9.10",
-        "@expo/plist": "^0.4.8",
-        "@expo/prebuild-config": "^54.0.8",
-        "@expo/schema-utils": "^0.1.8",
-        "@expo/spawn-async": "^1.7.2",
-        "@expo/ws-tunnel": "^1.0.1",
-        "@expo/xcpretty": "^4.3.0",
-        "@react-native/dev-middleware": "0.81.5",
-        "@urql/core": "^5.0.6",
-        "@urql/exchange-retry": "^1.3.0",
-        "accepts": "^1.3.8",
-        "arg": "^5.0.2",
-        "better-opn": "~3.0.2",
-        "bplist-creator": "0.1.0",
-        "bplist-parser": "^0.3.1",
-        "chalk": "^4.0.0",
-        "ci-info": "^3.3.0",
-        "compression": "^1.7.4",
-        "connect": "^3.7.0",
-        "debug": "^4.3.4",
-        "env-editor": "^0.4.1",
-        "expo-server": "^1.0.5",
-        "freeport-async": "^2.0.0",
-        "getenv": "^2.0.0",
-        "glob": "^13.0.0",
-        "lan-network": "^0.1.6",
-        "minimatch": "^9.0.0",
-        "node-forge": "^1.3.3",
-        "npm-package-arg": "^11.0.0",
-        "ora": "^3.4.0",
-        "picomatch": "^3.0.1",
-        "pretty-bytes": "^5.6.0",
-        "pretty-format": "^29.7.0",
-        "progress": "^2.0.3",
-        "prompts": "^2.3.2",
-        "qrcode-terminal": "0.11.0",
-        "require-from-string": "^2.0.2",
-        "requireg": "^0.2.2",
-        "resolve": "^1.22.2",
-        "resolve-from": "^5.0.0",
-        "resolve.exports": "^2.0.3",
-        "semver": "^7.6.0",
-        "send": "^0.19.0",
-        "slugify": "^1.3.4",
-        "source-map-support": "~0.5.21",
-        "stacktrace-parser": "^0.1.10",
-        "structured-headers": "^0.4.1",
-        "tar": "^7.5.2",
-        "terminal-link": "^2.1.1",
-        "undici": "^6.18.2",
-        "wrap-ansi": "^7.0.0",
-        "ws": "^8.12.1"
-      },
-      "bin": {
-        "expo-internal": "build/bin/cli"
-      },
-      "peerDependencies": {
-        "expo": "*",
-        "expo-router": "*",
-        "react-native": "*"
-      },
-      "peerDependenciesMeta": {
-        "expo-router": {
-          "optional": true
-        },
-        "react-native": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/expo/node_modules/@expo/cli/node_modules/@expo/prebuild-config": {
-      "version": "54.0.8",
-      "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-54.0.8.tgz",
-      "integrity": "sha512-EA7N4dloty2t5Rde+HP0IEE+nkAQiu4A/+QGZGT9mFnZ5KKjPPkqSyYcRvP5bhQE10D+tvz6X0ngZpulbMdbsg==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/config": "~12.0.13",
-        "@expo/config-plugins": "~54.0.4",
-        "@expo/config-types": "^54.0.10",
-        "@expo/image-utils": "^0.8.8",
-        "@expo/json-file": "^10.0.8",
-        "@react-native/normalize-colors": "0.81.5",
-        "debug": "^4.3.1",
-        "resolve-from": "^5.0.0",
-        "semver": "^7.6.0",
-        "xml2js": "0.6.0"
-      },
-      "peerDependencies": {
-        "expo": "*"
-      }
-    },
-    "node_modules/expo/node_modules/@expo/metro-config": {
-      "version": "54.0.14",
-      "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-54.0.14.tgz",
-      "integrity": "sha512-hxpLyDfOR4L23tJ9W1IbJJsG7k4lv2sotohBm/kTYyiG+pe1SYCAWsRmgk+H42o/wWf/HQjE5k45S5TomGLxNA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "^7.20.0",
-        "@babel/core": "^7.20.0",
-        "@babel/generator": "^7.20.5",
-        "@expo/config": "~12.0.13",
-        "@expo/env": "~2.0.8",
-        "@expo/json-file": "~10.0.8",
-        "@expo/metro": "~54.2.0",
-        "@expo/spawn-async": "^1.7.2",
-        "browserslist": "^4.25.0",
-        "chalk": "^4.1.0",
-        "debug": "^4.3.2",
-        "dotenv": "~16.4.5",
-        "dotenv-expand": "~11.0.6",
-        "getenv": "^2.0.0",
-        "glob": "^13.0.0",
-        "hermes-parser": "^0.29.1",
-        "jsc-safe-url": "^0.2.4",
-        "lightningcss": "^1.30.1",
-        "minimatch": "^9.0.0",
-        "postcss": "~8.4.32",
-        "resolve-from": "^5.0.0"
-      },
-      "peerDependencies": {
-        "expo": "*"
-      },
-      "peerDependenciesMeta": {
-        "expo": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/expo/node_modules/@expo/vector-icons": {
-      "version": "15.0.3",
-      "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz",
-      "integrity": "sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==",
-      "license": "MIT",
-      "peerDependencies": {
-        "expo-font": ">=14.0.4",
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/expo/node_modules/babel-preset-expo": {
-      "version": "54.0.10",
-      "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-54.0.10.tgz",
-      "integrity": "sha512-wTt7POavLFypLcPW/uC5v8y+mtQKDJiyGLzYCjqr9tx0Qc3vCXcDKk1iCFIj/++Iy5CWhhTflEa7VvVPNWeCfw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-module-imports": "^7.25.9",
-        "@babel/plugin-proposal-decorators": "^7.12.9",
-        "@babel/plugin-proposal-export-default-from": "^7.24.7",
-        "@babel/plugin-syntax-export-default-from": "^7.24.7",
-        "@babel/plugin-transform-class-static-block": "^7.27.1",
-        "@babel/plugin-transform-export-namespace-from": "^7.25.9",
-        "@babel/plugin-transform-flow-strip-types": "^7.25.2",
-        "@babel/plugin-transform-modules-commonjs": "^7.24.8",
-        "@babel/plugin-transform-object-rest-spread": "^7.24.7",
-        "@babel/plugin-transform-parameters": "^7.24.7",
-        "@babel/plugin-transform-private-methods": "^7.24.7",
-        "@babel/plugin-transform-private-property-in-object": "^7.24.7",
-        "@babel/plugin-transform-runtime": "^7.24.7",
-        "@babel/preset-react": "^7.22.15",
-        "@babel/preset-typescript": "^7.23.0",
-        "@react-native/babel-preset": "0.81.5",
-        "babel-plugin-react-compiler": "^1.0.0",
-        "babel-plugin-react-native-web": "~0.21.0",
-        "babel-plugin-syntax-hermes-parser": "^0.29.1",
-        "babel-plugin-transform-flow-enums": "^0.0.2",
-        "debug": "^4.3.4",
-        "resolve-from": "^5.0.0"
-      },
-      "peerDependencies": {
-        "@babel/runtime": "^7.20.0",
-        "expo": "*",
-        "react-refresh": ">=0.14.0 <1.0.0"
-      },
-      "peerDependenciesMeta": {
-        "@babel/runtime": {
-          "optional": true
-        },
-        "expo": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/expo/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/expo/node_modules/ci-info": {
-      "version": "3.9.0",
-      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
-      "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/sibiraj-s"
-        }
-      ],
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/expo/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/expo/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/expo/node_modules/expo-asset": {
-      "version": "12.0.12",
-      "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-12.0.12.tgz",
-      "integrity": "sha512-CsXFCQbx2fElSMn0lyTdRIyKlSXOal6ilLJd+yeZ6xaC7I9AICQgscY5nj0QcwgA+KYYCCEQEBndMsmj7drOWQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/image-utils": "^0.8.8",
-        "expo-constants": "~18.0.12"
-      },
-      "peerDependencies": {
-        "expo": "*",
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo/node_modules/expo-constants": {
-      "version": "18.0.13",
-      "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz",
-      "integrity": "sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@expo/config": "~12.0.13",
-        "@expo/env": "~2.0.8"
-      },
-      "peerDependencies": {
-        "expo": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo/node_modules/expo-file-system": {
-      "version": "19.0.21",
-      "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.21.tgz",
-      "integrity": "sha512-s3DlrDdiscBHtab/6W1osrjGL+C2bvoInPJD7sOwmxfJ5Woynv2oc+Fz1/xVXaE/V7HE/+xrHC/H45tu6lZzzg==",
-      "license": "MIT",
-      "peerDependencies": {
-        "expo": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo/node_modules/expo-font": {
-      "version": "14.0.11",
-      "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
-      "integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
-      "license": "MIT",
-      "peer": true,
-      "dependencies": {
-        "fontfaceobserver": "^2.1.0"
-      },
-      "peerDependencies": {
-        "expo": "*",
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/expo/node_modules/expo-keep-awake": {
-      "version": "15.0.8",
-      "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-15.0.8.tgz",
-      "integrity": "sha512-YK9M1VrnoH1vLJiQzChZgzDvVimVoriibiDIFLbQMpjYBnvyfUeHJcin/Gx1a+XgupNXy92EQJLgI/9ZuXajYQ==",
-      "license": "MIT",
-      "peerDependencies": {
-        "expo": "*",
-        "react": "*"
-      }
-    },
-    "node_modules/expo/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/expo/node_modules/hermes-estree": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz",
-      "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==",
-      "license": "MIT"
-    },
-    "node_modules/expo/node_modules/hermes-parser": {
-      "version": "0.29.1",
-      "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz",
-      "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==",
-      "license": "MIT",
-      "dependencies": {
-        "hermes-estree": "0.29.1"
-      }
-    },
-    "node_modules/expo/node_modules/picomatch": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz",
-      "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/expo/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/expo/node_modules/ws": {
-      "version": "8.19.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
-      "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": ">=5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/exponential-backoff": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz",
-      "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==",
-      "license": "Apache-2.0"
-    },
-    "node_modules/fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-      "license": "MIT"
-    },
-    "node_modules/fb-watchman": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
-      "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "bser": "2.1.1"
-      }
-    },
-    "node_modules/fill-range": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
-      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "license": "MIT",
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/finalhandler": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
-      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "on-finished": "~2.3.0",
-        "parseurl": "~1.3.3",
-        "statuses": "~1.5.0",
-        "unpipe": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/finalhandler/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/finalhandler/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "license": "MIT"
-    },
-    "node_modules/find-up": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-      "license": "MIT",
-      "dependencies": {
-        "locate-path": "^5.0.0",
-        "path-exists": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/flow-enums-runtime": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
-      "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
-      "license": "MIT"
-    },
-    "node_modules/fontfaceobserver": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
-      "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==",
-      "license": "BSD-2-Clause"
-    },
-    "node_modules/freeport-async": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz",
-      "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "license": "ISC"
-    },
-    "node_modules/fsevents": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-      "hasInstallScript": true,
-      "license": "MIT",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-      }
-    },
-    "node_modules/function-bind": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/gensync": {
-      "version": "1.0.0-beta.2",
-      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
-      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/get-caller-file": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-      "license": "ISC",
-      "engines": {
-        "node": "6.* || 8.* || >= 10.*"
-      }
-    },
-    "node_modules/get-package-type": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
-      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/getenv": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz",
-      "integrity": "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/glob": {
-      "version": "13.0.1",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.1.tgz",
-      "integrity": "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==",
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "minimatch": "^10.1.2",
-        "minipass": "^7.1.2",
-        "path-scurry": "^2.0.0"
-      },
-      "engines": {
-        "node": "20 || >=22"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/glob/node_modules/minimatch": {
-      "version": "10.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz",
-      "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==",
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "@isaacs/brace-expansion": "^5.0.1"
-      },
-      "engines": {
-        "node": "20 || >=22"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/global-dirs": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
-      "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
-      "license": "MIT",
-      "dependencies": {
-        "ini": "^1.3.4"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/graceful-fs": {
-      "version": "4.2.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
-      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
-      "license": "ISC"
-    },
-    "node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/hasown": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
-      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-      "license": "MIT",
-      "dependencies": {
-        "function-bind": "^1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/hermes-estree": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz",
-      "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==",
-      "license": "MIT"
-    },
-    "node_modules/hermes-parser": {
-      "version": "0.32.0",
-      "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz",
-      "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==",
-      "license": "MIT",
-      "dependencies": {
-        "hermes-estree": "0.32.0"
-      }
-    },
-    "node_modules/hosted-git-info": {
-      "version": "7.0.2",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
-      "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
-      "license": "ISC",
-      "dependencies": {
-        "lru-cache": "^10.0.1"
-      },
-      "engines": {
-        "node": "^16.14.0 || >=18.0.0"
-      }
-    },
-    "node_modules/hosted-git-info/node_modules/lru-cache": {
-      "version": "10.4.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
-      "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
-      "license": "ISC"
-    },
-    "node_modules/http-errors": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
-      "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
-      "license": "MIT",
-      "dependencies": {
-        "depd": "~2.0.0",
-        "inherits": "~2.0.4",
-        "setprototypeof": "~1.2.0",
-        "statuses": "~2.0.2",
-        "toidentifier": "~1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/express"
-      }
-    },
-    "node_modules/http-errors/node_modules/statuses": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
-      "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/https-proxy-agent": {
-      "version": "7.0.6",
-      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
-      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
-      "license": "MIT",
-      "dependencies": {
-        "agent-base": "^7.1.2",
-        "debug": "4"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/ieee754": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/ignore": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
-      "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/image-size": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
-      "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
-      "license": "MIT",
-      "dependencies": {
-        "queue": "6.0.2"
-      },
-      "bin": {
-        "image-size": "bin/image-size.js"
-      },
-      "engines": {
-        "node": ">=16.x"
-      }
-    },
-    "node_modules/imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8.19"
-      }
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
-      "license": "ISC",
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "license": "ISC"
-    },
-    "node_modules/ini": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
-      "license": "ISC"
-    },
-    "node_modules/invariant": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
-      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-      "license": "MIT",
-      "dependencies": {
-        "loose-envify": "^1.0.0"
-      }
-    },
-    "node_modules/is-core-module": {
-      "version": "2.16.1",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
-      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
-      "license": "MIT",
-      "dependencies": {
-        "hasown": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-docker": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-      "license": "MIT",
-      "bin": {
-        "is-docker": "cli.js"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
-    "node_modules/is-wsl": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
-      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
-      "license": "MIT",
-      "dependencies": {
-        "is-docker": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-      "license": "ISC"
-    },
-    "node_modules/istanbul-lib-coverage": {
-      "version": "3.2.2",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
-      "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/istanbul-lib-instrument": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
-      "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@babel/core": "^7.12.3",
-        "@babel/parser": "^7.14.7",
-        "@istanbuljs/schema": "^0.1.2",
-        "istanbul-lib-coverage": "^3.2.0",
-        "semver": "^6.3.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/istanbul-lib-instrument/node_modules/semver": {
-      "version": "6.3.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      }
-    },
-    "node_modules/jest-environment-node": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
-      "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/environment": "^29.7.0",
-        "@jest/fake-timers": "^29.7.0",
-        "@jest/types": "^29.6.3",
-        "@types/node": "*",
-        "jest-mock": "^29.7.0",
-        "jest-util": "^29.7.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-get-type": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
-      "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
-      "license": "MIT",
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-haste-map": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
-      "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/types": "^29.6.3",
-        "@types/graceful-fs": "^4.1.3",
-        "@types/node": "*",
-        "anymatch": "^3.0.3",
-        "fb-watchman": "^2.0.0",
-        "graceful-fs": "^4.2.9",
-        "jest-regex-util": "^29.6.3",
-        "jest-util": "^29.7.0",
-        "jest-worker": "^29.7.0",
-        "micromatch": "^4.0.4",
-        "walker": "^1.0.8"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "^2.3.2"
-      }
-    },
-    "node_modules/jest-message-util": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
-      "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "^7.12.13",
-        "@jest/types": "^29.6.3",
-        "@types/stack-utils": "^2.0.0",
-        "chalk": "^4.0.0",
-        "graceful-fs": "^4.2.9",
-        "micromatch": "^4.0.4",
-        "pretty-format": "^29.7.0",
-        "slash": "^3.0.0",
-        "stack-utils": "^2.0.3"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-message-util/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/jest-message-util/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/jest-message-util/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/jest-message-util/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/jest-message-util/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/jest-message-util/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-message-util/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-mock": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
-      "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/types": "^29.6.3",
-        "@types/node": "*",
-        "jest-util": "^29.7.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-regex-util": {
-      "version": "29.6.3",
-      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
-      "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
-      "license": "MIT",
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-util": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
-      "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/types": "^29.6.3",
-        "@types/node": "*",
-        "chalk": "^4.0.0",
-        "ci-info": "^3.2.0",
-        "graceful-fs": "^4.2.9",
-        "picomatch": "^2.2.3"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-util/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/jest-util/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/jest-util/node_modules/ci-info": {
-      "version": "3.9.0",
-      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
-      "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/sibiraj-s"
-        }
-      ],
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-util/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/jest-util/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/jest-util/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-util/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-validate": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
-      "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/types": "^29.6.3",
-        "camelcase": "^6.2.0",
-        "chalk": "^4.0.0",
-        "jest-get-type": "^29.6.3",
-        "leven": "^3.1.0",
-        "pretty-format": "^29.7.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-validate/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/jest-validate/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/jest-validate/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/jest-validate/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/jest-validate/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-validate/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-worker": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
-      "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/node": "*",
-        "jest-util": "^29.7.0",
-        "merge-stream": "^2.0.0",
-        "supports-color": "^8.0.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/jest-worker/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/jest-worker/node_modules/supports-color": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
-      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/supports-color?sponsor=1"
-      }
-    },
-    "node_modules/jimp-compact": {
-      "version": "0.16.1",
-      "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz",
-      "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==",
-      "license": "MIT"
-    },
-    "node_modules/js-tokens": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-      "license": "MIT"
-    },
-    "node_modules/js-yaml": {
-      "version": "3.14.2",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
-      "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
-      "license": "MIT",
-      "dependencies": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/jsc-safe-url": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
-      "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
-      "license": "0BSD"
-    },
-    "node_modules/jsesc": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
-      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
-      "license": "MIT",
-      "bin": {
-        "jsesc": "bin/jsesc"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/json5": {
-      "version": "2.2.3",
-      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
-      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
-      "license": "MIT",
-      "bin": {
-        "json5": "lib/cli.js"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/kleur": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
-      "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/lan-network": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.1.7.tgz",
-      "integrity": "sha512-mnIlAEMu4OyEvUNdzco9xpuB9YVcPkQec+QsgycBCtPZvEqWPCDPfbAE4OJMdBBWpZWtpCn1xw9jJYlwjWI5zQ==",
-      "license": "MIT",
-      "bin": {
-        "lan-network": "dist/lan-network-cli.js"
-      }
-    },
-    "node_modules/leven": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
-      "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/lighthouse-logger": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
-      "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "debug": "^2.6.9",
-        "marky": "^1.2.2"
-      }
-    },
-    "node_modules/lighthouse-logger/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/lighthouse-logger/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "license": "MIT"
-    },
-    "node_modules/lightningcss": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz",
-      "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==",
-      "license": "MPL-2.0",
-      "dependencies": {
-        "detect-libc": "^2.0.3"
-      },
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      },
-      "optionalDependencies": {
-        "lightningcss-android-arm64": "1.31.1",
-        "lightningcss-darwin-arm64": "1.31.1",
-        "lightningcss-darwin-x64": "1.31.1",
-        "lightningcss-freebsd-x64": "1.31.1",
-        "lightningcss-linux-arm-gnueabihf": "1.31.1",
-        "lightningcss-linux-arm64-gnu": "1.31.1",
-        "lightningcss-linux-arm64-musl": "1.31.1",
-        "lightningcss-linux-x64-gnu": "1.31.1",
-        "lightningcss-linux-x64-musl": "1.31.1",
-        "lightningcss-win32-arm64-msvc": "1.31.1",
-        "lightningcss-win32-x64-msvc": "1.31.1"
-      }
-    },
-    "node_modules/lightningcss-android-arm64": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz",
-      "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==",
-      "cpu": [
-        "arm64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "android"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-darwin-arm64": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz",
-      "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==",
-      "cpu": [
-        "arm64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-darwin-x64": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz",
-      "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==",
-      "cpu": [
-        "x64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-freebsd-x64": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz",
-      "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==",
-      "cpu": [
-        "x64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "freebsd"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-linux-arm-gnueabihf": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz",
-      "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==",
-      "cpu": [
-        "arm"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-linux-arm64-gnu": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz",
-      "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==",
-      "cpu": [
-        "arm64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-linux-arm64-musl": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz",
-      "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==",
-      "cpu": [
-        "arm64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-linux-x64-gnu": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz",
-      "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==",
-      "cpu": [
-        "x64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-linux-x64-musl": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz",
-      "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==",
-      "cpu": [
-        "x64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "linux"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-win32-arm64-msvc": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz",
-      "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==",
-      "cpu": [
-        "arm64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lightningcss-win32-x64-msvc": {
-      "version": "1.31.1",
-      "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz",
-      "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==",
-      "cpu": [
-        "x64"
-      ],
-      "license": "MPL-2.0",
-      "optional": true,
-      "os": [
-        "win32"
-      ],
-      "engines": {
-        "node": ">= 12.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/parcel"
-      }
-    },
-    "node_modules/lines-and-columns": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "license": "MIT"
-    },
-    "node_modules/locate-path": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-      "license": "MIT",
-      "dependencies": {
-        "p-locate": "^4.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/lodash.debounce": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
-      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
-      "license": "MIT"
-    },
-    "node_modules/lodash.throttle": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-      "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
-      "license": "MIT"
-    },
-    "node_modules/log-symbols": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
-      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
-      "license": "MIT",
-      "dependencies": {
-        "chalk": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/loose-envify": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
-      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
-      "license": "MIT",
-      "dependencies": {
-        "js-tokens": "^3.0.0 || ^4.0.0"
-      },
-      "bin": {
-        "loose-envify": "cli.js"
-      }
-    },
-    "node_modules/lru-cache": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
-      "license": "ISC",
-      "dependencies": {
-        "yallist": "^3.0.2"
-      }
-    },
-    "node_modules/makeerror": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
-      "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "tmpl": "1.0.5"
-      }
-    },
-    "node_modules/marky": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz",
-      "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==",
-      "license": "Apache-2.0"
-    },
-    "node_modules/memoize-one": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
-      "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
-      "license": "MIT"
-    },
-    "node_modules/merge-stream": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
-      "license": "MIT"
-    },
-    "node_modules/metro": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro/-/metro-0.83.3.tgz",
-      "integrity": "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/code-frame": "^7.24.7",
-        "@babel/core": "^7.25.2",
-        "@babel/generator": "^7.25.0",
-        "@babel/parser": "^7.25.3",
-        "@babel/template": "^7.25.0",
-        "@babel/traverse": "^7.25.3",
-        "@babel/types": "^7.25.2",
-        "accepts": "^1.3.7",
-        "chalk": "^4.0.0",
-        "ci-info": "^2.0.0",
-        "connect": "^3.6.5",
-        "debug": "^4.4.0",
-        "error-stack-parser": "^2.0.6",
-        "flow-enums-runtime": "^0.0.6",
-        "graceful-fs": "^4.2.4",
-        "hermes-parser": "0.32.0",
-        "image-size": "^1.0.2",
-        "invariant": "^2.2.4",
-        "jest-worker": "^29.7.0",
-        "jsc-safe-url": "^0.2.2",
-        "lodash.throttle": "^4.1.1",
-        "metro-babel-transformer": "0.83.3",
-        "metro-cache": "0.83.3",
-        "metro-cache-key": "0.83.3",
-        "metro-config": "0.83.3",
-        "metro-core": "0.83.3",
-        "metro-file-map": "0.83.3",
-        "metro-resolver": "0.83.3",
-        "metro-runtime": "0.83.3",
-        "metro-source-map": "0.83.3",
-        "metro-symbolicate": "0.83.3",
-        "metro-transform-plugins": "0.83.3",
-        "metro-transform-worker": "0.83.3",
-        "mime-types": "^2.1.27",
-        "nullthrows": "^1.1.1",
-        "serialize-error": "^2.1.0",
-        "source-map": "^0.5.6",
-        "throat": "^5.0.0",
-        "ws": "^7.5.10",
-        "yargs": "^17.6.2"
-      },
-      "bin": {
-        "metro": "src/cli.js"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-babel-transformer": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz",
-      "integrity": "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/core": "^7.25.2",
-        "flow-enums-runtime": "^0.0.6",
-        "hermes-parser": "0.32.0",
-        "nullthrows": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-cache": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.3.tgz",
-      "integrity": "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==",
-      "license": "MIT",
-      "dependencies": {
-        "exponential-backoff": "^3.1.1",
-        "flow-enums-runtime": "^0.0.6",
-        "https-proxy-agent": "^7.0.5",
-        "metro-core": "0.83.3"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-cache-key": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.3.tgz",
-      "integrity": "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==",
-      "license": "MIT",
-      "dependencies": {
-        "flow-enums-runtime": "^0.0.6"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-config": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.83.3.tgz",
-      "integrity": "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==",
-      "license": "MIT",
-      "dependencies": {
-        "connect": "^3.6.5",
-        "flow-enums-runtime": "^0.0.6",
-        "jest-validate": "^29.7.0",
-        "metro": "0.83.3",
-        "metro-cache": "0.83.3",
-        "metro-core": "0.83.3",
-        "metro-runtime": "0.83.3",
-        "yaml": "^2.6.1"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-core": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.83.3.tgz",
-      "integrity": "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==",
-      "license": "MIT",
-      "dependencies": {
-        "flow-enums-runtime": "^0.0.6",
-        "lodash.throttle": "^4.1.1",
-        "metro-resolver": "0.83.3"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-file-map": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.3.tgz",
-      "integrity": "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "^4.4.0",
-        "fb-watchman": "^2.0.0",
-        "flow-enums-runtime": "^0.0.6",
-        "graceful-fs": "^4.2.4",
-        "invariant": "^2.2.4",
-        "jest-worker": "^29.7.0",
-        "micromatch": "^4.0.4",
-        "nullthrows": "^1.1.1",
-        "walker": "^1.0.7"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-minify-terser": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz",
-      "integrity": "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==",
-      "license": "MIT",
-      "dependencies": {
-        "flow-enums-runtime": "^0.0.6",
-        "terser": "^5.15.0"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-resolver": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.3.tgz",
-      "integrity": "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==",
-      "license": "MIT",
-      "dependencies": {
-        "flow-enums-runtime": "^0.0.6"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-runtime": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.83.3.tgz",
-      "integrity": "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/runtime": "^7.25.0",
-        "flow-enums-runtime": "^0.0.6"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-source-map": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.83.3.tgz",
-      "integrity": "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/traverse": "^7.25.3",
-        "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
-        "@babel/types": "^7.25.2",
-        "flow-enums-runtime": "^0.0.6",
-        "invariant": "^2.2.4",
-        "metro-symbolicate": "0.83.3",
-        "nullthrows": "^1.1.1",
-        "ob1": "0.83.3",
-        "source-map": "^0.5.6",
-        "vlq": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-symbolicate": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz",
-      "integrity": "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==",
-      "license": "MIT",
-      "dependencies": {
-        "flow-enums-runtime": "^0.0.6",
-        "invariant": "^2.2.4",
-        "metro-source-map": "0.83.3",
-        "nullthrows": "^1.1.1",
-        "source-map": "^0.5.6",
-        "vlq": "^1.0.0"
-      },
-      "bin": {
-        "metro-symbolicate": "src/index.js"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-transform-plugins": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz",
-      "integrity": "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/core": "^7.25.2",
-        "@babel/generator": "^7.25.0",
-        "@babel/template": "^7.25.0",
-        "@babel/traverse": "^7.25.3",
-        "flow-enums-runtime": "^0.0.6",
-        "nullthrows": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro-transform-worker": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz",
-      "integrity": "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/core": "^7.25.2",
-        "@babel/generator": "^7.25.0",
-        "@babel/parser": "^7.25.3",
-        "@babel/types": "^7.25.2",
-        "flow-enums-runtime": "^0.0.6",
-        "metro": "0.83.3",
-        "metro-babel-transformer": "0.83.3",
-        "metro-cache": "0.83.3",
-        "metro-cache-key": "0.83.3",
-        "metro-minify-terser": "0.83.3",
-        "metro-source-map": "0.83.3",
-        "metro-transform-plugins": "0.83.3",
-        "nullthrows": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/metro/node_modules/@babel/code-frame": {
-      "version": "7.29.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
-      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
-      "license": "MIT",
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.28.5",
-        "js-tokens": "^4.0.0",
-        "picocolors": "^1.1.1"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/metro/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/metro/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/metro/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/metro/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/metro/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/metro/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/micromatch": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
-      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
-      "license": "MIT",
-      "dependencies": {
-        "braces": "^3.0.3",
-        "picomatch": "^2.3.1"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
-    "node_modules/mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-      "license": "MIT",
-      "bin": {
-        "mime": "cli.js"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/mime-db": {
-      "version": "1.52.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
-      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime-types": {
-      "version": "2.1.35",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
-      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-      "license": "MIT",
-      "dependencies": {
-        "mime-db": "1.52.0"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mimic-fn": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
-      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "9.0.5",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
-      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/minimist": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/minipass": {
-      "version": "7.1.2",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
-      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      }
-    },
-    "node_modules/minizlib": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
-      "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
-      "license": "MIT",
-      "dependencies": {
-        "minipass": "^7.1.2"
-      },
-      "engines": {
-        "node": ">= 18"
-      }
-    },
-    "node_modules/mkdirp": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-      "license": "MIT",
-      "bin": {
-        "mkdirp": "bin/cmd.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/mz": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
-      "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
-      "license": "MIT",
-      "dependencies": {
-        "any-promise": "^1.0.0",
-        "object-assign": "^4.0.1",
-        "thenify-all": "^1.0.0"
-      }
-    },
-    "node_modules/nanoid": {
-      "version": "3.3.11",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
-      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "bin": {
-        "nanoid": "bin/nanoid.cjs"
-      },
-      "engines": {
-        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-      }
-    },
-    "node_modules/negotiator": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
-      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/nested-error-stacks": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz",
-      "integrity": "sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==",
-      "license": "MIT"
-    },
-    "node_modules/node-forge": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz",
-      "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==",
-      "license": "(BSD-3-Clause OR GPL-2.0)",
-      "engines": {
-        "node": ">= 6.13.0"
-      }
-    },
-    "node_modules/node-int64": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
-      "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
-      "license": "MIT"
-    },
-    "node_modules/node-releases": {
-      "version": "2.0.27",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
-      "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
-      "license": "MIT"
-    },
-    "node_modules/normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/npm-package-arg": {
-      "version": "11.0.3",
-      "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz",
-      "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==",
-      "license": "ISC",
-      "dependencies": {
-        "hosted-git-info": "^7.0.0",
-        "proc-log": "^4.0.0",
-        "semver": "^7.3.5",
-        "validate-npm-package-name": "^5.0.0"
-      },
-      "engines": {
-        "node": "^16.14.0 || >=18.0.0"
-      }
-    },
-    "node_modules/nullthrows": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz",
-      "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
-      "license": "MIT"
-    },
-    "node_modules/ob1": {
-      "version": "0.83.3",
-      "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.83.3.tgz",
-      "integrity": "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA==",
-      "license": "MIT",
-      "dependencies": {
-        "flow-enums-runtime": "^0.0.6"
-      },
-      "engines": {
-        "node": ">=20.19.4"
-      }
-    },
-    "node_modules/object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/on-finished": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
-      "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
-      "license": "MIT",
-      "dependencies": {
-        "ee-first": "1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/on-headers": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
-      "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "license": "ISC",
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/onetime": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
-      "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
-      "license": "MIT",
-      "dependencies": {
-        "mimic-fn": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/open": {
-      "version": "7.4.2",
-      "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
-      "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
-      "license": "MIT",
-      "dependencies": {
-        "is-docker": "^2.0.0",
-        "is-wsl": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ora": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
-      "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
-      "license": "MIT",
-      "dependencies": {
-        "chalk": "^2.4.2",
-        "cli-cursor": "^2.1.0",
-        "cli-spinners": "^2.0.0",
-        "log-symbols": "^2.2.0",
-        "strip-ansi": "^5.2.0",
-        "wcwidth": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/ora/node_modules/ansi-regex": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
-      "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/ora/node_modules/strip-ansi": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
-      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^4.1.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/p-limit": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-      "license": "MIT",
-      "dependencies": {
-        "yocto-queue": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-locate": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-      "license": "MIT",
-      "dependencies": {
-        "p-limit": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/p-locate/node_modules/p-limit": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-      "license": "MIT",
-      "dependencies": {
-        "p-try": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-try": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/parse-png": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz",
-      "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==",
-      "license": "MIT",
-      "dependencies": {
-        "pngjs": "^3.3.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/parseurl": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-parse": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "license": "MIT"
-    },
-    "node_modules/path-scurry": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
-      "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "lru-cache": "^11.0.0",
-        "minipass": "^7.1.2"
-      },
-      "engines": {
-        "node": "20 || >=22"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/path-scurry/node_modules/lru-cache": {
-      "version": "11.2.5",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz",
-      "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==",
-      "license": "BlueOak-1.0.0",
-      "engines": {
-        "node": "20 || >=22"
-      }
-    },
-    "node_modules/picocolors": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
-      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
-      "license": "ISC"
-    },
-    "node_modules/picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/pirates": {
-      "version": "4.0.7",
-      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
-      "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/plist": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
-      "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@xmldom/xmldom": "^0.8.8",
-        "base64-js": "^1.5.1",
-        "xmlbuilder": "^15.1.1"
-      },
-      "engines": {
-        "node": ">=10.4.0"
-      }
-    },
-    "node_modules/pngjs": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
-      "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/postcss": {
-      "version": "8.4.49",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
-      "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/postcss"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "nanoid": "^3.3.7",
-        "picocolors": "^1.1.1",
-        "source-map-js": "^1.2.1"
-      },
-      "engines": {
-        "node": "^10 || ^12 || >=14"
-      }
-    },
-    "node_modules/pretty-bytes": {
-      "version": "5.6.0",
-      "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
-      "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/pretty-format": {
-      "version": "29.7.0",
-      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
-      "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/schemas": "^29.6.3",
-        "ansi-styles": "^5.0.0",
-        "react-is": "^18.0.0"
-      },
-      "engines": {
-        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
-      }
-    },
-    "node_modules/pretty-format/node_modules/ansi-styles": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
-      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/proc-log": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
-      "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
-      "license": "ISC",
-      "engines": {
-        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
-      }
-    },
-    "node_modules/progress": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
-      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/promise": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
-      "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
-      "license": "MIT",
-      "dependencies": {
-        "asap": "~2.0.6"
-      }
-    },
-    "node_modules/prompts": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
-      "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
-      "license": "MIT",
-      "dependencies": {
-        "kleur": "^3.0.3",
-        "sisteransi": "^1.0.5"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/punycode": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
-      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/qrcode-terminal": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz",
-      "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==",
-      "bin": {
-        "qrcode-terminal": "bin/qrcode-terminal.js"
-      }
-    },
-    "node_modules/queue": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
-      "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
-      "license": "MIT",
-      "dependencies": {
-        "inherits": "~2.0.3"
-      }
-    },
-    "node_modules/range-parser": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/rc": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
-      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
-      "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
-      "dependencies": {
-        "deep-extend": "^0.6.0",
-        "ini": "~1.3.0",
-        "minimist": "^1.2.0",
-        "strip-json-comments": "~2.0.1"
-      },
-      "bin": {
-        "rc": "cli.js"
-      }
-    },
-    "node_modules/react": {
-      "version": "19.1.0",
-      "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
-      "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/react-devtools-core": {
-      "version": "6.1.5",
-      "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz",
-      "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==",
-      "license": "MIT",
-      "dependencies": {
-        "shell-quote": "^1.6.1",
-        "ws": "^7"
-      }
-    },
-    "node_modules/react-is": {
-      "version": "18.3.1",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
-      "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
-      "license": "MIT"
-    },
-    "node_modules/react-native": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
-      "integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jest/create-cache-key-function": "^29.7.0",
-        "@react-native/assets-registry": "0.81.5",
-        "@react-native/codegen": "0.81.5",
-        "@react-native/community-cli-plugin": "0.81.5",
-        "@react-native/gradle-plugin": "0.81.5",
-        "@react-native/js-polyfills": "0.81.5",
-        "@react-native/normalize-colors": "0.81.5",
-        "@react-native/virtualized-lists": "0.81.5",
-        "abort-controller": "^3.0.0",
-        "anser": "^1.4.9",
-        "ansi-regex": "^5.0.0",
-        "babel-jest": "^29.7.0",
-        "babel-plugin-syntax-hermes-parser": "0.29.1",
-        "base64-js": "^1.5.1",
-        "commander": "^12.0.0",
-        "flow-enums-runtime": "^0.0.6",
-        "glob": "^7.1.1",
-        "invariant": "^2.2.4",
-        "jest-environment-node": "^29.7.0",
-        "memoize-one": "^5.0.0",
-        "metro-runtime": "^0.83.1",
-        "metro-source-map": "^0.83.1",
-        "nullthrows": "^1.1.1",
-        "pretty-format": "^29.7.0",
-        "promise": "^8.3.0",
-        "react-devtools-core": "^6.1.5",
-        "react-refresh": "^0.14.0",
-        "regenerator-runtime": "^0.13.2",
-        "scheduler": "0.26.0",
-        "semver": "^7.1.3",
-        "stacktrace-parser": "^0.1.10",
-        "whatwg-fetch": "^3.0.0",
-        "ws": "^6.2.3",
-        "yargs": "^17.6.2"
-      },
-      "bin": {
-        "react-native": "cli.js"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      },
-      "peerDependencies": {
-        "@types/react": "^19.1.0",
-        "react": "^19.1.0"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/react-native-is-edge-to-edge": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz",
-      "integrity": "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==",
-      "license": "MIT",
-      "peerDependencies": {
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/react-native-safe-area-context": {
-      "version": "5.6.2",
-      "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz",
-      "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==",
-      "license": "MIT",
-      "peerDependencies": {
-        "react": "*",
-        "react-native": "*"
-      }
-    },
-    "node_modules/react-native/node_modules/@react-native/virtualized-lists": {
-      "version": "0.81.5",
-      "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.5.tgz",
-      "integrity": "sha512-UVXgV/db25OPIvwZySeToXD/9sKKhOdkcWmmf4Jh8iBZuyfML+/5CasaZ1E7Lqg6g3uqVQq75NqIwkYmORJMPw==",
-      "license": "MIT",
-      "dependencies": {
-        "invariant": "^2.2.4",
-        "nullthrows": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 20.19.4"
-      },
-      "peerDependencies": {
-        "@types/react": "^19.1.0",
-        "react": "*",
-        "react-native": "*"
-      },
-      "peerDependenciesMeta": {
-        "@types/react": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/react-native/node_modules/brace-expansion": {
-      "version": "1.1.12",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
-      "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/react-native/node_modules/commander": {
-      "version": "12.1.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
-      "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/react-native/node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
-      "license": "ISC",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/react-native/node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/react-native/node_modules/ws": {
-      "version": "6.2.3",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
-      "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
-      "license": "MIT",
-      "dependencies": {
-        "async-limiter": "~1.0.0"
-      }
-    },
-    "node_modules/react-refresh": {
-      "version": "0.14.2",
-      "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
-      "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
-      "license": "MIT",
-      "peer": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/regenerate": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
-      "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
-      "license": "MIT"
-    },
-    "node_modules/regenerate-unicode-properties": {
-      "version": "10.2.2",
-      "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz",
-      "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==",
-      "license": "MIT",
-      "dependencies": {
-        "regenerate": "^1.4.2"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/regenerator-runtime": {
-      "version": "0.13.11",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
-      "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
-      "license": "MIT"
-    },
-    "node_modules/regexpu-core": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz",
-      "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==",
-      "license": "MIT",
-      "dependencies": {
-        "regenerate": "^1.4.2",
-        "regenerate-unicode-properties": "^10.2.2",
-        "regjsgen": "^0.8.0",
-        "regjsparser": "^0.13.0",
-        "unicode-match-property-ecmascript": "^2.0.0",
-        "unicode-match-property-value-ecmascript": "^2.2.1"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/regjsgen": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz",
-      "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
-      "license": "MIT"
-    },
-    "node_modules/regjsparser": {
-      "version": "0.13.0",
-      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz",
-      "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==",
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "jsesc": "~3.1.0"
-      },
-      "bin": {
-        "regjsparser": "bin/parser"
-      }
-    },
-    "node_modules/require-directory": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/require-from-string": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
-      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/requireg": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz",
-      "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==",
-      "dependencies": {
-        "nested-error-stacks": "~2.0.1",
-        "rc": "~1.2.7",
-        "resolve": "~1.7.1"
-      },
-      "engines": {
-        "node": ">= 4.0.0"
-      }
-    },
-    "node_modules/requireg/node_modules/resolve": {
-      "version": "1.7.1",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
-      "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
-      "license": "MIT",
-      "dependencies": {
-        "path-parse": "^1.0.5"
-      }
-    },
-    "node_modules/resolve": {
-      "version": "1.22.11",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
-      "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
-      "license": "MIT",
-      "dependencies": {
-        "is-core-module": "^2.16.1",
-        "path-parse": "^1.0.7",
-        "supports-preserve-symlinks-flag": "^1.0.0"
-      },
-      "bin": {
-        "resolve": "bin/resolve"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/resolve-from": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
-      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/resolve-global": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz",
-      "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==",
-      "license": "MIT",
-      "dependencies": {
-        "global-dirs": "^0.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/resolve-workspace-root": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz",
-      "integrity": "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==",
-      "license": "MIT"
-    },
-    "node_modules/resolve.exports": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
-      "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/restore-cursor": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
-      "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
-      "license": "MIT",
-      "dependencies": {
-        "onetime": "^2.0.0",
-        "signal-exit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "deprecated": "Rimraf versions prior to v4 are no longer supported",
-      "license": "ISC",
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/rimraf/node_modules/brace-expansion": {
-      "version": "1.1.12",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
-      "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/rimraf/node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
-      "license": "ISC",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/rimraf/node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/sax": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz",
-      "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==",
-      "license": "BlueOak-1.0.0",
-      "engines": {
-        "node": ">=11.0.0"
-      }
-    },
-    "node_modules/scheduler": {
-      "version": "0.26.0",
-      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
-      "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
-      "license": "MIT"
-    },
-    "node_modules/semver": {
-      "version": "7.7.4",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
-      "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/send": {
-      "version": "0.19.2",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
-      "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "encodeurl": "~2.0.0",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "~0.5.2",
-        "http-errors": "~2.0.1",
-        "mime": "1.6.0",
-        "ms": "2.1.3",
-        "on-finished": "~2.4.1",
-        "range-parser": "~1.2.1",
-        "statuses": "~2.0.2"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/send/node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/send/node_modules/debug/node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "license": "MIT"
-    },
-    "node_modules/send/node_modules/encodeurl": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
-      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/send/node_modules/on-finished": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "license": "MIT",
-      "dependencies": {
-        "ee-first": "1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/send/node_modules/statuses": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
-      "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/serialize-error": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
-      "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/serve-static": {
-      "version": "1.16.3",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
-      "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
-      "license": "MIT",
-      "dependencies": {
-        "encodeurl": "~2.0.0",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.3",
-        "send": "~0.19.1"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/serve-static/node_modules/encodeurl": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
-      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/setprototypeof": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
-      "license": "ISC"
-    },
-    "node_modules/shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "license": "MIT",
-      "dependencies": {
-        "shebang-regex": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/shell-quote": {
-      "version": "1.8.3",
-      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
-      "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/signal-exit": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
-      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
-      "license": "ISC"
-    },
-    "node_modules/simple-plist": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz",
-      "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==",
-      "license": "MIT",
-      "dependencies": {
-        "bplist-creator": "0.1.0",
-        "bplist-parser": "0.3.1",
-        "plist": "^3.0.5"
-      }
-    },
-    "node_modules/sisteransi": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
-      "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
-      "license": "MIT"
-    },
-    "node_modules/slash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/slugify": {
-      "version": "1.6.6",
-      "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
-      "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/source-map": {
-      "version": "0.5.7",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/source-map-js": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
-      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/source-map-support": {
-      "version": "0.5.21",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-      "license": "MIT",
-      "dependencies": {
-        "buffer-from": "^1.0.0",
-        "source-map": "^0.6.0"
-      }
-    },
-    "node_modules/source-map-support/node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/sprintf-js": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/stack-utils": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
-      "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
-      "license": "MIT",
-      "dependencies": {
-        "escape-string-regexp": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/stack-utils/node_modules/escape-string-regexp": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
-      "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/stackframe": {
-      "version": "1.3.4",
-      "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
-      "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
-      "license": "MIT"
-    },
-    "node_modules/stacktrace-parser": {
-      "version": "0.1.11",
-      "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
-      "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
-      "license": "MIT",
-      "dependencies": {
-        "type-fest": "^0.7.1"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/statuses": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/stream-buffers": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz",
-      "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==",
-      "license": "Unlicense",
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "license": "MIT",
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-json-comments": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/structured-headers": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz",
-      "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==",
-      "license": "MIT"
-    },
-    "node_modules/sucrase": {
-      "version": "3.35.1",
-      "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
-      "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/gen-mapping": "^0.3.2",
-        "commander": "^4.0.0",
-        "lines-and-columns": "^1.1.6",
-        "mz": "^2.7.0",
-        "pirates": "^4.0.1",
-        "tinyglobby": "^0.2.11",
-        "ts-interface-checker": "^0.1.9"
-      },
-      "bin": {
-        "sucrase": "bin/sucrase",
-        "sucrase-node": "bin/sucrase-node"
-      },
-      "engines": {
-        "node": ">=16 || 14 >=14.17"
-      }
-    },
-    "node_modules/sucrase/node_modules/commander": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
-      "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/supports-hyperlinks": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
-      "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0",
-        "supports-color": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/supports-hyperlinks/node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/supports-hyperlinks/node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/supports-preserve-symlinks-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/tar": {
-      "version": "7.5.7",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
-      "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
-      "license": "BlueOak-1.0.0",
-      "dependencies": {
-        "@isaacs/fs-minipass": "^4.0.0",
-        "chownr": "^3.0.0",
-        "minipass": "^7.1.2",
-        "minizlib": "^3.1.0",
-        "yallist": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/tar/node_modules/yallist": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
-      "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
-      "license": "BlueOak-1.0.0",
-      "engines": {
-        "node": ">=18"
-      }
-    },
-    "node_modules/temp-dir": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
-      "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/terminal-link": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
-      "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-escapes": "^4.2.1",
-        "supports-hyperlinks": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/terser": {
-      "version": "5.46.0",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz",
-      "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==",
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "@jridgewell/source-map": "^0.3.3",
-        "acorn": "^8.15.0",
-        "commander": "^2.20.0",
-        "source-map-support": "~0.5.20"
-      },
-      "bin": {
-        "terser": "bin/terser"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/terser/node_modules/commander": {
-      "version": "2.20.3",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
-      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
-      "license": "MIT"
-    },
-    "node_modules/test-exclude": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
-      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
-      "license": "ISC",
-      "dependencies": {
-        "@istanbuljs/schema": "^0.1.2",
-        "glob": "^7.1.4",
-        "minimatch": "^3.0.4"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/test-exclude/node_modules/brace-expansion": {
-      "version": "1.1.12",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
-      "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/test-exclude/node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
-      "license": "ISC",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/test-exclude/node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/thenify": {
-      "version": "3.3.1",
-      "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
-      "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
-      "license": "MIT",
-      "dependencies": {
-        "any-promise": "^1.0.0"
-      }
-    },
-    "node_modules/thenify-all": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
-      "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
-      "license": "MIT",
-      "dependencies": {
-        "thenify": ">= 3.1.0 < 4"
-      },
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/throat": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
-      "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
-      "license": "MIT"
-    },
-    "node_modules/tinyglobby": {
-      "version": "0.2.15",
-      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
-      "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
-      "license": "MIT",
-      "dependencies": {
-        "fdir": "^6.5.0",
-        "picomatch": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=12.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/SuperchupuDev"
-      }
-    },
-    "node_modules/tinyglobby/node_modules/fdir": {
-      "version": "6.5.0",
-      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
-      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=12.0.0"
-      },
-      "peerDependencies": {
-        "picomatch": "^3 || ^4"
-      },
-      "peerDependenciesMeta": {
-        "picomatch": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/tinyglobby/node_modules/picomatch": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
-      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
-      "license": "MIT",
-      "peer": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/tmpl": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
-      "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "license": "MIT",
-      "dependencies": {
-        "is-number": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
-    "node_modules/toidentifier": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
-    "node_modules/ts-interface-checker": {
-      "version": "0.1.13",
-      "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
-      "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
-      "license": "Apache-2.0"
-    },
-    "node_modules/type-detect": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
-      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/type-fest": {
-      "version": "0.7.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
-      "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
-      "license": "(MIT OR CC0-1.0)",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/typescript": {
-      "version": "5.9.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
-      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
-      "dev": true,
-      "license": "Apache-2.0",
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=14.17"
-      }
-    },
-    "node_modules/undici": {
-      "version": "6.23.0",
-      "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
-      "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=18.17"
-      }
-    },
-    "node_modules/undici-types": {
-      "version": "7.16.0",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
-      "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
-      "license": "MIT"
-    },
-    "node_modules/unicode-canonical-property-names-ecmascript": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
-      "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unicode-match-property-ecmascript": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
-      "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
-      "license": "MIT",
-      "dependencies": {
-        "unicode-canonical-property-names-ecmascript": "^2.0.0",
-        "unicode-property-aliases-ecmascript": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unicode-match-property-value-ecmascript": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz",
-      "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unicode-property-aliases-ecmascript": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz",
-      "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/unique-string": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
-      "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
-      "license": "MIT",
-      "dependencies": {
-        "crypto-random-string": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/update-browserslist-db": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
-      "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/browserslist"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/browserslist"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "escalade": "^3.2.0",
-        "picocolors": "^1.1.1"
-      },
-      "bin": {
-        "update-browserslist-db": "cli.js"
-      },
-      "peerDependencies": {
-        "browserslist": ">= 4.21.0"
-      }
-    },
-    "node_modules/utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
-    "node_modules/uuid": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
-      "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==",
-      "license": "MIT",
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/validate-npm-package-name": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz",
-      "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==",
-      "license": "ISC",
-      "engines": {
-        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
-      }
-    },
-    "node_modules/vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/vlq": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
-      "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
-      "license": "MIT"
-    },
-    "node_modules/walker": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
-      "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "makeerror": "1.0.12"
-      }
-    },
-    "node_modules/wcwidth": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
-      "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
-      "license": "MIT",
-      "dependencies": {
-        "defaults": "^1.0.3"
-      }
-    },
-    "node_modules/webidl-conversions": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
-      "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/whatwg-fetch": {
-      "version": "3.6.20",
-      "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
-      "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
-      "license": "MIT"
-    },
-    "node_modules/whatwg-url-without-unicode": {
-      "version": "8.0.0-3",
-      "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz",
-      "integrity": "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==",
-      "license": "MIT",
-      "dependencies": {
-        "buffer": "^5.4.3",
-        "punycode": "^2.1.1",
-        "webidl-conversions": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "license": "ISC",
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "node-which": "bin/node-which"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/wonka": {
-      "version": "6.3.5",
-      "resolved": "https://registry.npmjs.org/wonka/-/wonka-6.3.5.tgz",
-      "integrity": "sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw==",
-      "license": "MIT"
-    },
-    "node_modules/wrap-ansi": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/wrap-ansi/node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "license": "ISC"
-    },
-    "node_modules/write-file-atomic": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
-      "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
-      "license": "ISC",
-      "dependencies": {
-        "imurmurhash": "^0.1.4",
-        "signal-exit": "^3.0.7"
-      },
-      "engines": {
-        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
-      }
-    },
-    "node_modules/ws": {
-      "version": "7.5.10",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
-      "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.3.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": "^5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/xcode": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz",
-      "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "simple-plist": "^1.1.0",
-        "uuid": "^7.0.3"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/xml2js": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz",
-      "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==",
-      "license": "MIT",
-      "dependencies": {
-        "sax": ">=0.6.0",
-        "xmlbuilder": "~11.0.0"
-      },
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/xml2js/node_modules/xmlbuilder": {
-      "version": "11.0.1",
-      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
-      "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/xmlbuilder": {
-      "version": "15.1.1",
-      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
-      "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
-    "node_modules/y18n": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
-      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/yallist": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
-      "license": "ISC"
-    },
-    "node_modules/yaml": {
-      "version": "2.8.2",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
-      "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
-      "license": "ISC",
-      "bin": {
-        "yaml": "bin.mjs"
-      },
-      "engines": {
-        "node": ">= 14.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/eemeli"
-      }
-    },
-    "node_modules/yargs": {
-      "version": "17.7.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
-      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
-      "license": "MIT",
-      "dependencies": {
-        "cliui": "^8.0.1",
-        "escalade": "^3.1.1",
-        "get-caller-file": "^2.0.5",
-        "require-directory": "^2.1.1",
-        "string-width": "^4.2.3",
-        "y18n": "^5.0.5",
-        "yargs-parser": "^21.1.1"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/yargs-parser": {
-      "version": "21.1.1",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
-      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/yocto-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    }
-  }
-}
diff --git a/package.json b/package.json
deleted file mode 100644 (file)
index 0e7b4c4..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{
-  "name": "conseiller-crypto-mobile",
-  "version": "1.0.0",
-  "main": "index.ts",
-  "scripts": {
-    "start": "expo start",
-    "android": "expo start --android",
-    "ios": "expo start --ios",
-    "web": "expo start --web"
-  },
-  "dependencies": {
-    "expo": "~54.0.33",
-    "expo-status-bar": "~3.0.9",
-    "react": "19.1.0",
-    "react-native": "0.81.5",
-    "react-native-safe-area-context": "~5.6.0"
-  },
-  "devDependencies": {
-    "@types/react": "~19.1.0",
-    "typescript": "~5.9.2"
-  },
-  "private": true
-}
diff --git a/server/.env.example b/server/.env.example
new file mode 100644 (file)
index 0000000..6619b95
--- /dev/null
@@ -0,0 +1,67 @@
+# =========================================================
+# CONFIGURATION WALL-E-TTE - ENVIRONNEMENT
+# =========================================================
+# Copie ce fichier en .env et remplis tes vraies valeurs
+# IMPORTANT : Ne JAMAIS commit le fichier .env sur Git !
+# =========================================================
+
+# ─────────────────────────────────────────────────────────
+# BASE DE DONNÉES
+# ─────────────────────────────────────────────────────────
+DB_HOST=students2.promotion-sociale-marche.be
+DB_PORT=3306
+DB_NAME=wallette
+DB_USER=walletteuser
+DB_PASS=LCCaece2026.
+# ─────────────────────────────────────────────────────────
+# EMAIL (Nodemailer)
+# ─────────────────────────────────────────────────────────
+# Pour Gmail :
+# 1. Active l'authentification à 2 facteurs
+# 2. Génère un "App Password" : https://myaccount.google.com/apppasswords
+# 3. Utilise ce password ici (pas ton vrai password Gmail)
+
+MAIL_HOST=sandbox.smtp.mailtrap.iom
+MAIL_PORT=2525
+MAIL_USER=02f2d21aa711ee
+MAIL_PASS=0423dbc39fc410
+
+# Alternative : Mailtrap (pour tests, n'envoie pas vraiment)
+# MAIL_HOST=smtp.mailtrap.io
+# MAIL_PORT=2525
+# MAIL_USER=ton-username-mailtrap
+# MAIL_PASS=ton-password-mailtrap
+
+# ─────────────────────────────────────────────────────────
+# TELEGRAM (optionnel - à configurer plus tard)
+# ─────────────────────────────────────────────────────────
+# 1. Parle à @BotFather sur Telegram
+# 2. Crée un bot avec /newbot
+# 3. Récupère le TOKEN
+
+TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
+TELEGRAM_CHAT_ID=123456789
+
+# Pour trouver ton CHAT_ID :
+# 1. Envoie un message à ton bot
+# 2. Va sur : https://api.telegram.org/bot<TON_TOKEN>/getUpdates
+# 3. Cherche "chat":{"id":123456789}
+
+# ─────────────────────────────────────────────────────────
+# DISCORD (optionnel)
+# ─────────────────────────────────────────────────────────
+DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/123456/abcdef
+
+# ─────────────────────────────────────────────────────────
+# SERVEUR
+# ─────────────────────────────────────────────────────────
+NODE_ENV=development
+PORT=3000
+
+# ─────────────────────────────────────────────────────────
+# NOTES
+# ─────────────────────────────────────────────────────────
+# Pour créer ton fichier .env :
+# 1. Copie ce fichier : cp .env.example .env
+# 2. Remplis tes vraies valeurs
+# 3. Vérifie que .env est dans .gitignore
diff --git a/server/DOC-FRONTEND-SOCKET_POUR_OCEANE_ET_THIBAUD.md b/server/DOC-FRONTEND-SOCKET_POUR_OCEANE_ET_THIBAUD.md
new file mode 100644 (file)
index 0000000..5639e1a
--- /dev/null
@@ -0,0 +1,227 @@
+# 📡 Guide Socket.IO - Alertes Temps Réel
+
+## Pour Océane (Web) et Thibaud (Mobile)
+
+Ce document explique comment recevoir les alertes en temps réel depuis le serveur.
+
+---
+
+## 🔧 Installation
+
+### Web (JavaScript/React)
+```bash
+npm install socket.io-client
+```
+
+### Mobile (React Native / Expo)
+```bash
+npm install socket.io-client
+```
+
+---
+
+## Connexion au serveur
+
+### Code TypeScript/JavaScript
+
+```typescript
+import { io, Socket } from 'socket.io-client';
+
+// URL du serveur (à adapter selon l'environnement)
+const SERVER_URL = 'http://localhost:3000';
+
+// Créer la connexion
+const socket: Socket = io(SERVER_URL);
+
+// Événement : connexion établie
+socket.on('connect', () => {
+    console.log('✅ Connecté au serveur Socket.IO');
+
+    // IMPORTANT : S'authentifier avec l'userId
+    const userId = 'user-123'; // Récupérer depuis votre auth
+    socket.emit('auth', userId);
+});
+
+// Événement : authentification confirmée
+socket.on('auth_success', (data) => {
+    console.log('✅ Authentifié:', data.message);
+});
+
+// Événement : déconnexion
+socket.on('disconnect', (reason) => {
+    console.log('❌ Déconnecté:', reason);
+});
+```
+
+---
+
+## Recevoir les alertes
+
+```typescript
+// Structure d'une alerte reçue
+interface Alert {
+    action: 'BUY' | 'SELL' | 'HOLD';
+    pair: string;           // ex: 'BTC/EUR'
+    confidence: number;     // 0 à 1
+    reason: string;         // Explication du signal
+    alertLevel: 'INFO' | 'WARNING' | 'CRITICAL';
+    timestamp: number;      // Unix timestamp ms
+    price?: number;         // Prix au moment du signal
+}
+
+// Écouter les alertes
+socket.on('alert', (alert: Alert) => {
+    console.log('🔔 Nouvelle alerte:', alert);
+
+    // Exemple de traitement
+    if (alert.alertLevel === 'CRITICAL') {
+        // Notification urgente
+        showUrgentNotification(alert);
+    } else {
+        // Notification normale
+        showNotification(alert);
+    }
+});
+```
+
+---
+
+## Tester la connexion
+
+```typescript
+// Envoyer un ping de test
+socket.emit('ping_alerts');
+
+// Recevoir
+socket.on('pong_alerts', (data) => {
+    console.log('Connexion OK, latence:', Date.now() - data.timestamp, 'ms');
+});
+```
+
+---
+
+## Exemple complet React Native (Thibaud)
+
+```typescript
+// services/socketService.ts
+import { io, Socket } from 'socket.io-client';
+import { Alert } from '../types/DashboardSummary';
+
+class SocketService {
+    private socket: Socket | null = null;
+    private listeners: ((alert: Alert) => void)[] = [];
+
+    connect(serverUrl: string, userId: string) {
+        this.socket = io(serverUrl);
+
+        this.socket.on('connect', () => {
+            console.log('Socket connecté');
+            this.socket?.emit('auth', userId);
+        });
+
+        this.socket.on('alert', (alert: Alert) => {
+            this.listeners.forEach(cb => cb(alert));
+        });
+    }
+
+    onAlert(callback: (alert: Alert) => void) {
+        this.listeners.push(callback);
+    }
+
+    disconnect() {
+        this.socket?.disconnect();
+        this.socket = null;
+    }
+}
+
+export const socketService = new SocketService();
+```
+
+```typescript
+// Dans un composant React Native
+import { useEffect, useState } from 'react';
+import { socketService } from '../services/socketService';
+
+export function useLiveAlerts(userId: string) {
+    const [alerts, setAlerts] = useState<Alert[]>([]);
+
+    useEffect(() => {
+        socketService.connect('http://YOUR_SERVER:3000', userId);
+
+        socketService.onAlert((alert) => {
+            setAlerts(prev => [alert, ...prev]);
+        });
+
+        return () => socketService.disconnect();
+    }, [userId]);
+
+    return alerts;
+}
+```
+
+---
+
+## Exemple complet React Web (Océane)
+
+```typescript
+// hooks/useSocket.ts
+import { useEffect, useState } from 'react';
+import { io, Socket } from 'socket.io-client';
+
+interface Alert {
+    action: 'BUY' | 'SELL' | 'HOLD';
+    pair: string;
+    confidence: number;
+    reason: string;
+    alertLevel: 'INFO' | 'WARNING' | 'CRITICAL';
+    timestamp: number;
+    price?: number;
+}
+
+export function useSocket(serverUrl: string, userId: string) {
+    const [socket, setSocket] = useState<Socket | null>(null);
+    const [connected, setConnected] = useState(false);
+    const [alerts, setAlerts] = useState<Alert[]>([]);
+
+    useEffect(() => {
+        const newSocket = io(serverUrl);
+
+        newSocket.on('connect', () => {
+            setConnected(true);
+            newSocket.emit('auth', userId);
+        });
+
+        newSocket.on('disconnect', () => {
+            setConnected(false);
+        });
+
+        newSocket.on('alert', (alert: Alert) => {
+            setAlerts(prev => [alert, ...prev].slice(0, 50)); // Garder 50 max
+        });
+
+        setSocket(newSocket);
+
+        return () => {
+            newSocket.disconnect();
+        };
+    }, [serverUrl, userId]);
+
+    return { socket, connected, alerts };
+}
+```
+
+---
+
+## Récapitulatif des événements
+
+| Event | Direction | Description |
+|-------|-----------|-------------|
+| `auth` | Client → Serveur | Envoyer l'userId pour s'authentifier |
+| `auth_success` | Serveur → Client | Confirmation d'authentification |
+| `alert` | Serveur → Client | Réception d'une alerte |
+| `ping_alerts` | Client → Serveur | Test de connexion |
+| `pong_alerts` | Serveur → Client | Réponse au ping |
+
+---
+
+
diff --git a/server/EXAMPLE-other-project.js b/server/EXAMPLE-other-project.js
new file mode 100644 (file)
index 0000000..0538d04
--- /dev/null
@@ -0,0 +1,125 @@
+// =========================================================
+// EXEMPLE : Utilisation du module dans UN AUTRE PROJET
+// =========================================================
+// Ce fichier montre comment un projet DIFFÉRENT de Wall-e-tte
+// peut utiliser le module d'alertes
+// =========================================================
+
+/*
+    CONTEXTE :
+    ton module d'alertes.
+
+    Leur projet a :
+    - Une DB avec des tables différentes
+    - Une structure différente
+    - Mais ils veulent ton système d'alertes !
+*/
+
+// =========================================================
+// 1. LEUR CONFIGURATION DB (différente de Wall-e-tte)
+// =========================================================
+import mysql from 'mysql2/promise';
+
+// Leur connexion DB (avec leurs credentials)
+const theirDb = mysql.createPool({
+    host: 'their-server.com',
+    user: 'their-user',
+    password: 'their-password',
+    database: 'crypto_tracker_db'
+});
+
+// =========================================================
+// 2. IMPORT DU MODULE ALERTS
+// =========================================================
+// Ils peuvent installer via npm ou copier les fichiers
+// import { createAlertsRepo, createAlertsService } from '@wall-e-tte/alerts-module';
+
+// Ou si les fichiers sont copiés dans leur projet :
+import { createAlertsRepo } from './vendors/wall-e-tte-alerts/alerts.repo.js';
+import { createAlertsService } from './vendors/wall-e-tte-alerts/alerts.service.js';
+
+// =========================================================
+// 3. INITIALISATION AVEC LEURS TABLES
+// =========================================================
+const alertsRepo = createAlertsRepo(theirDb, {
+    alertsTable: 'notification_rules',      // ← Leur nom
+    usersTable: 'accounts',                 // ← Leur nom
+    eventsTable: 'notification_history'     // ← Leur nom
+});
+
+const alertsService = createAlertsService(alertsRepo);
+
+// =========================================================
+// 4. UTILISATION - EXACTEMENT PAREIL !
+// =========================================================
+async function handleCryptoSignal() {
+
+    // Leur signal (même structure que Wall-e-tte)
+    const signal = {
+        userId: 'account-789',              // Leur ID format
+        pairId: 42,                          // Leur ID format
+        pair: 'ETH/USD',
+        action: 'SELL',
+        confidence: 0.92,
+        criticality: 'CRITICAL',
+        reason: 'Major resistance level reached, volume increasing'
+    };
+
+    //Le module utilise LEURS tables
+    await alertsService.processSignal(signal);
+
+    console.log('Signal traité avec succès dans CryptoTracker !');
+}
+
+// =========================================================
+// 5. STRUCTURE DE TABLE (différente de Wall-e-tte)
+// =========================================================
+/*
+    CREATE TABLE notification_rules (
+        rule_id VARCHAR(36) PRIMARY KEY,
+        user_id VARCHAR(36),              -- Pointent vers 'accounts'
+        enabled TINYINT(1),
+        severity ENUM('CRITICAL','WARNING','INFO'),
+        min_confidence DECIMAL(5,4),
+        channel ENUM('WEB','CONSOLE','EMAIL','DISCORD','TELEGRAM'),
+        cooldown_ms BIGINT,
+        last_notified_at_ms BIGINT,
+        -- ... autres colonnes
+        FOREIGN KEY (user_id) REFERENCES accounts(user_id)
+    );
+
+    CREATE TABLE accounts (
+        user_id VARCHAR(36) PRIMARY KEY,
+        email VARCHAR(255),
+        -- ... autres colonnes
+    );
+
+    CREATE TABLE notification_history (
+        alert_event_id VARCHAR(36) PRIMARY KEY,
+        rule_id VARCHAR(36),
+        timestamp_ms BIGINT,
+        severity ENUM('CRITICAL','WARNING','INFO'),
+        channel VARCHAR(20),
+        send_status ENUM('PENDING','SENT','FAILED'),
+        -- ... autres colonnes
+    );
+*/
+
+// =========================================================
+// RÉSULTAT :
+// =========================================================
+/*
+    Le module marche dans d'autres projets
+    pas de mondif du code
+    Il y aura juste à configurr les noms de tables
+*/
+
+// =========================================================
+// EXPORT POUR UTILISATION DANS LEUR APP
+// =========================================================
+export { alertsRepo, alertsService };
+export default alertsService;
+
+// Dans leur app :
+// import alertsService from './alerts-integration.js';
+// await alertsService.processSignal(signal);
diff --git a/server/config/db.js b/server/config/db.js
new file mode 100644 (file)
index 0000000..a9bbc9f
--- /dev/null
@@ -0,0 +1,62 @@
+// =========================================================
+// CONFIGURATION DE LA BASE DE DONNÉES
+// =========================================================
+// crée une connexion réutilisable à MySQL/MariaDB
+// utilise un "pool" de connexions
+// =========================================================
+
+import dotenv from 'dotenv';
+import mysql from 'mysql2/promise';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+// =========================================================
+// CONFIGURATION DU CHEMIN
+// =========================================================
+// créer le filename avec fileURLToPath
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+// =========================================================
+// CHARGEMENT DES VARIABLES D'ENVIRONNEMENT
+// =========================================================
+// charge .env qui contient les credits DB
+// .env doit être à la racine du dossier server/
+dotenv.config({ path: path.resolve(__dirname, '../.env') });
+
+// =========================================================
+// CRÉATION DU POOL DE CONNEXIONS
+// =========================================================
+// Un pool = plusieurs connexions réutilisables
+const db = mysql.createPool({
+    host: process.env.DB_HOST || 'localhost',
+    port: process.env.DB_PORT || 33020,
+    user: process.env.DB_USER,
+    password: process.env.DB_PASS,
+    database: process.env.DB_NAME || 'wallete',
+
+    // Paramètres du pool
+    waitForConnections: true,    // Attend si toutes les connexions sont occupées
+    connectionLimit: 10,          // Max 10 connexions simultanées
+    queueLimit: 0                 // Pas de limite de file d'attente
+});
+
+// =========================================================
+// TEST DE CONNEXION
+// =========================================================
+// Vérifie au démarrage que la DB est accessible
+db.getConnection()
+    .then(connection => {
+        console.log('Connexion à la base de données réussie');
+        connection.release(); // Libère la connexion dans le pool
+    })
+    .catch(err => {
+        console.error('Erreur de connexion à la base de données:', err.message);
+        console.error('Vérifie ton fichier .env !');
+    });
+
+// =========================================================
+// EXPORT
+// =========================================================
+// On exporte le pool pour l'utiliser dans les repositories
+export default db;
diff --git a/server/modules/alerts/adapters/mysql.adapter.js b/server/modules/alerts/adapters/mysql.adapter.js
new file mode 100644 (file)
index 0000000..a6a1e14
--- /dev/null
@@ -0,0 +1,220 @@
+// =========================================================
+// MYSQL ADAPTER - Couche d'accès MySQL
+// =========================================================
+// RÔLE : Contient TOUT le SQL pour MySQL/MariaDB
+// =========================================================
+// Ce fichier isole le SQL du reste du module.
+// Pour utiliser MongoDB, créer un mongo.adapter.js
+// qui implémente les mêmes méthodes.
+// =========================================================
+
+import { v4 as uuidv4 } from 'uuid';
+
+// =========================================================
+// FACTORY FUNCTION : Créer un adapter MySQL
+// =========================================================
+/**
+ * Crée un adapter MySQL pour le module d'alertes
+ *
+ * @param {Object} dbConnection - Connexion MySQL (mysql2/promise)
+ * @param {Object} options - Configuration des noms de tables
+ * @param {string} options.alertsTable - Nom de la table des règles (défaut: 'alert_rules')
+ * @param {string} options.usersTable - Nom de la table users (défaut: 'users')
+ * @param {string} options.eventsTable - Nom de la table events (défaut: 'alert_events')
+ *
+ * @returns {Object} Adapter avec toutes les méthodes d'accès DB
+ *
+ * @example
+ * import db from './config/db.js';
+ * import { createMySQLAdapter } from './adapters/mysql.adapter.js';
+ *
+ * const adapter = createMySQLAdapter(db);
+ * const rules = await adapter.findActiveRulesForSignal('user-123', 1);
+ */
+export function createMySQLAdapter(dbConnection, options = {}) {
+
+    // =========================================================
+    // CONFIGURATION DES NOMS DE TABLES
+    // =========================================================
+    const tables = {
+        alerts: options.alertsTable || 'alert_rules',
+        users: options.usersTable || 'users',
+        events: options.eventsTable || 'alert_events'
+    };
+
+    console.log(`🔌 Adapter MySQL configuré avec tables: ${JSON.stringify(tables)}`);
+
+    // =========================================================
+    // RETOURNER L'OBJET ADAPTER
+    // =========================================================
+    return {
+
+        // =====================================================
+        // 1. RÉCUPÉRER LES RÈGLES D'ALERTE ACTIVES
+        // =====================================================
+        async findActiveRulesForSignal(userId, pairId) {
+            try {
+                const sql = `
+                    SELECT
+                        ar.*,
+                        u.email
+                    FROM ${tables.alerts} ar
+                    JOIN ${tables.users} u ON ar.user_id = u.user_id
+                    WHERE ar.enabled = 1
+                        AND ar.user_id = ?
+                        AND (ar.pair_id = ? OR ar.pair_id IS NULL)
+                    ORDER BY ar.severity DESC
+                `;
+
+                const [rows] = await dbConnection.execute(sql, [userId, pairId]);
+
+                console.log(`[MySQL] Règles trouvées pour user ${userId} : ${rows.length}`);
+                return rows;
+
+            } catch (error) {
+                console.error('[MySQL] Erreur dans findActiveRulesForSignal:', error);
+                throw error;
+            }
+        },
+
+        // =====================================================
+        // 2. SAUVEGARDER UN ÉVÉNEMENT D'ALERTE
+        // =====================================================
+        async saveAlertEvent(eventData) {
+            try {
+                const sql = `
+                    INSERT INTO ${tables.events} (
+                        alert_event_id,
+                        rule_id,
+                        timestamp_ms,
+                        severity,
+                        channel,
+                        send_status,
+                        title,
+                        message,
+                        signal_action,
+                        confidence,
+                        correlation_id,
+                        created_at_ms
+                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+                `;
+
+                const values = [
+                    eventData.alert_event_id || uuidv4(),
+                    eventData.rule_id,
+                    eventData.timestamp_ms || Date.now(),
+                    eventData.severity,
+                    eventData.channel,
+                    eventData.send_status,
+                    eventData.title,
+                    eventData.message,
+                    eventData.signal_action,
+                    eventData.confidence,
+                    eventData.correlation_id || null,
+                    Date.now()
+                ];
+
+                await dbConnection.execute(sql, values);
+                console.log(`[MySQL] Événement d'alerte sauvegardé : ${eventData.title}`);
+
+            } catch (error) {
+                console.error('[MySQL] Erreur dans saveAlertEvent:', error);
+                throw error;
+            }
+        },
+
+        // =====================================================
+        // 3. METTRE À JOUR LA DERNIÈRE NOTIFICATION
+        // =====================================================
+        async updateLastNotified(ruleId, timestamp) {
+            try {
+                const sql = `
+                    UPDATE ${tables.alerts}
+                    SET last_notified_at_ms = ?,
+                        updated_at_ms = ?
+                    WHERE rule_id = ?
+                `;
+
+                await dbConnection.execute(sql, [timestamp, Date.now(), ruleId]);
+                console.log(`[MySQL] Timestamp mis à jour pour rule ${ruleId}`);
+
+            } catch (error) {
+                console.error('[MySQL] Erreur dans updateLastNotified:', error);
+                throw error;
+            }
+        },
+
+        // =====================================================
+        // 4. RÉCUPÉRER L'HISTORIQUE DES ALERTES
+        // =====================================================
+        async getAlertHistory(userId, limit = 50) {
+            try {
+                const sql = `
+                    SELECT
+                        ae.*,
+                        ar.channel,
+                        ar.rule_type
+                    FROM ${tables.events} ae
+                    JOIN ${tables.alerts} ar ON ae.rule_id = ar.rule_id
+                    WHERE ar.user_id = ?
+                    ORDER BY ae.timestamp_ms DESC
+                    LIMIT ?
+                `;
+
+                const [rows] = await dbConnection.execute(sql, [userId, limit]);
+                return rows;
+
+            } catch (error) {
+                console.error('[MySQL] Erreur dans getAlertHistory:', error);
+                throw error;
+            }
+        },
+
+        // =====================================================
+        // 5. CRÉER UNE NOUVELLE RÈGLE D'ALERTE
+        // =====================================================
+        async createAlertRule(ruleData) {
+            try {
+                const sql = `
+                    INSERT INTO ${tables.alerts} (
+                        rule_id,
+                        user_id,
+                        pair_id,
+                        enabled,
+                        rule_type,
+                        severity,
+                        min_confidence,
+                        channel,
+                        params,
+                        cooldown_ms,
+                        created_at_ms,
+                        updated_at_ms
+                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+                `;
+
+                const values = [
+                    ruleData.rule_id || uuidv4(),
+                    ruleData.user_id,
+                    ruleData.pair_id || null,
+                    ruleData.enabled !== undefined ? ruleData.enabled : 1,
+                    ruleData.rule_type,
+                    ruleData.severity || 'INFO',
+                    ruleData.min_confidence || 0.75,
+                    ruleData.channel || 'EMAIL',
+                    JSON.stringify(ruleData.params || {}),
+                    ruleData.cooldown_ms || 60000,
+                    Date.now(),
+                    Date.now()
+                ];
+
+                await dbConnection.execute(sql, values);
+                console.log(`[MySQL] Règle d'alerte créée : ${ruleData.rule_type}`);
+
+            } catch (error) {
+                console.error('[MySQL] Erreur dans createAlertRule:', error);
+                throw error;
+            }
+        }
+    };
+}
+
diff --git a/server/modules/alerts/alerts.controller.js b/server/modules/alerts/alerts.controller.js
new file mode 100644 (file)
index 0000000..c2a495e
--- /dev/null
@@ -0,0 +1,204 @@
+// =========================================================
+// ALERTS CONTROLLER - VERSION RÉUTILISABLE
+// =========================================================
+// RÔLE : Gestion des requêtes et réponses HTTP
+// =========================================================
+
+
+/**
+ * Crée un controller d'alertes réutilisable
+ *
+ * @param {Object} alertsService - Service d'alertes (créé par createAlertsService)
+ * @param {Object} alertsRepo - Repository d'alertes (pour certaines méthodes)
+ *
+ * @returns {Object} Controller avec toutes les méthodes
+ */
+export function createAlertsController(alertsService, alertsRepo) {
+
+    console.log("Controller d'alertes initialisé");
+
+    return {
+
+        // =====================================================
+        // POST /api/alerts/process-signal
+        // =====================================================
+        /**
+         * Endpoint pour traiter un signal crypto
+         *
+         * Appelé par le module Strategy (Sacha) quand il
+         * génère un signal BUY/SELL/HOLD
+         *
+         * Body attendu :
+         * {
+         *   "userId": "uuid",
+         *   "pairId": 1,
+         *   "pair": "BTC/EUR",
+         *   "action": "BUY",
+         *   "confidence": 0.87,
+         *   "criticality": "WARNING",
+         *   "reason": "Indicators show...",
+         *   "priceAtSignal": 45000.50
+         * }
+         */
+        async processSignal(req, res) {
+            try {
+                // ==================================================================================
+                // 1. RÉCUPÉRER LES DONNÉES DU BODY
+                // ==================================================================================
+                const signal = req.body;
+
+                // ==================================================================================
+                // 2. VALIDATION DES DONNÉES
+                // ==================================================================================
+                // Vérifier que tous les champs obligatoires sont présents
+                const requiredFields = ['userId', 'pairId', 'pair', 'action', 'confidence', 'criticality'];
+                /**
+                 *  on remplit le tableau des champs manquant ou faux du contenu de signal
+                 */
+                const missingFields = requiredFields.filter(field => !signal[field]);
+                // dans ce cas on retourne une erreur et le noms des champs en cause
+                if (missingFields.length > 0) {
+                    return res.status(400).json({
+                        success: false,
+                        error: 'Champs manquants',
+                        missingFields: missingFields
+                    });
+                }
+
+                // Valider le format de action
+                const validActions = ['BUY', 'SELL', 'HOLD', 'STOP_LOSS'];
+                if (!validActions.includes(signal.action)) {
+                    return res.status(400).json({
+                        success: false,
+                        error: `Action invalide. Doit être: ${validActions.join(', ')}`
+                    });
+                }
+
+                // Valider le format de criticality
+                const validCriticalities = ['CRITICAL', 'WARNING', 'INFO'];
+                if (!validCriticalities.includes(signal.criticality)) {
+                    return res.status(400).json({
+                        success: false,
+                        error: `Criticality invalide. Doit être: ${validCriticalities.join(', ')}`
+                    });
+                }
+
+                // Valider la confidence (doit être entre 0 et 1)
+                if (signal.confidence < 0 || signal.confidence > 1) {
+                    return res.status(400).json({
+                        success: false,
+                        error: 'Confidence doit être entre 0 et 1'
+                    });
+                }
+
+                // =================================================================================
+                // 3. APPELER LE SERVICE (injecté)
+                // =================================================================================
+                // Le service contient toute la logique
+                await alertsService.processSignal(signal);
+
+                // =================================================================================
+                // 4. RÉPONDRE AU CLIENT
+                // =================================================================================
+                res.status(200).json({
+                    success: true,
+                    message: 'Signal traité avec succès',
+                    signal: {
+                        action: signal.action,
+                        pair: signal.pair,
+                        confidence: signal.confidence
+                    }
+                });
+
+            } catch (error) {
+                // =================================================================================
+                // GESTION DES ERREURS
+                // =================================================================================
+                console.error('❌ Erreur dans processSignal controller:', error);
+
+                res.status(500).json({
+                    success: false,
+                    error: 'Erreur serveur lors du traitement du signal',
+                    details: process.env.NODE_ENV === 'development' ? error.message : undefined
+                });
+            }
+        },
+
+        // =====================================================
+        // GET /api/alerts/rules/:userId
+        // =====================================================
+        /**
+         * Récupère toutes les règles d'alerte d'un utilisateur
+         *
+         * Utile pour afficher la configuration dans l'interface
+         */
+        async getRules(req, res) {
+            try {
+                const { userId } = req.params;
+
+                // Validation
+                if (!userId) {
+                    return res.status(400).json({
+                        success: false,
+                        error: 'userId manquant'
+                    });
+                }
+
+                // Récupérer les règles (via repo injecté)
+                const rules = await alertsRepo.findActiveRulesForSignal(userId, null);
+
+                res.status(200).json({
+                    success: true,
+                    count: rules.length,
+                    rules: rules
+                });
+
+            } catch (error) {
+                console.error('Erreur dans getRules controller:', error);
+
+                res.status(500).json({
+                    success: false,
+                    error: 'Erreur serveur'
+                });
+            }
+        },
+
+        // =====================================================
+        // GET /api/alerts/history/:userId
+        // =====================================================
+        /**
+         * Récupère l'historique des alertes d'un utilisateur
+         */
+        async getHistory(req, res) {
+            try {
+                const { userId } = req.params;
+                const limit = parseInt(req.query.limit) || 50;
+
+                if (!userId) {
+                    return res.status(400).json({
+                        success: false,
+                        error: 'userId manquant'
+                    });
+                }
+
+                // Récupérer l'historique (via repo injecté)
+                const history = await alertsRepo.getAlertHistory(userId, limit);
+
+                res.status(200).json({
+                    success: true,
+                    count: history.length,
+                    history: history
+                });
+
+            } catch (error) {
+                console.error('Erreur dans getHistory controller:', error);
+
+                res.status(500).json({
+                    success: false,
+                    error: 'Erreur serveur'
+                });
+            }
+        }
+    };
+}
+
diff --git a/server/modules/alerts/alerts.repo.js b/server/modules/alerts/alerts.repo.js
new file mode 100644 (file)
index 0000000..bf26e2a
--- /dev/null
@@ -0,0 +1,103 @@
+// =========================================================
+// ALERTS REPOSITORY - VERSION AVEC ADAPTER
+// =========================================================
+// RÔLE : Interface entre le Service et l'Adapter
+// =========================================================
+// Le repo ne fait PLUS de SQL directement.
+// Il délègue à l'adapter injecté.
+// =========================================================
+
+// =========================================================
+// FACTORY FUNCTION : Créer un repository
+// =========================================================
+/**
+ * Crée un repository d'alertes réutilisable
+ *
+ * @param {Object} adapter - Adapter de base de données (MySQL, MongoDB, etc.)
+ * @returns {Object} Repository avec toutes les méthodes
+ *
+ * @example
+ * // Avec MySQL
+ * import { createMySQLAdapter } from './adapters/mysql.adapter.js';
+ * import { createAlertsRepo } from './alerts.repo.js';
+ *
+ * const adapter = createMySQLAdapter(db);
+ * const repo = createAlertsRepo(adapter);
+ *
+ * @example
+ * // Avec MongoDB (adapter à créer)
+ * import { createMongoAdapter } from './adapters/mongo.adapter.js';
+ *
+ * const adapter = createMongoAdapter(mongoClient);
+ * const repo = createAlertsRepo(adapter);
+ */
+export function createAlertsRepo(adapter) {
+
+    console.log(`Repository d'alertes initialisé`);
+
+// =========================================================
+// RETOURNER L'OBJET REPOSITORY
+// =========================================================
+    return {
+
+        // =====================================================
+        // 1. RÉCUPÉRER LES RÈGLES D'ALERTE ACTIVES
+        // =====================================================
+        /**
+         * Récupère les règles d'alerte pour un signal donné
+         * @param {string} userId - ID de l'utilisateur
+         * @param {number} pairId - ID de la paire crypto
+         * @returns {Promise<Array>} Liste des règles actives
+         */
+        async findActiveRulesForSignal(userId, pairId) {
+            return adapter.findActiveRulesForSignal(userId, pairId);
+        },
+
+        // =====================================================
+        // 2. SAUVEGARDER UN ÉVÉNEMENT D'ALERTE
+        // =====================================================
+        /**
+         * Enregistre qu'une alerte a été envoyée
+         * @param {Object} eventData - Données de l'événement
+         */
+        async saveAlertEvent(eventData) {
+            return adapter.saveAlertEvent(eventData);
+        },
+
+        // =====================================================
+        // 3. METTRE À JOUR LA DERNIÈRE NOTIFICATION
+        // =====================================================
+        /**
+         * Met à jour le timestamp pour le cooldown (anti-spam)
+         * @param {string} ruleId - ID de la règle
+         * @param {number} timestamp - Timestamp en millisecondes
+         */
+        async updateLastNotified(ruleId, timestamp) {
+            return adapter.updateLastNotified(ruleId, timestamp);
+        },
+
+        // =====================================================
+        // 4. RÉCUPÉRER L'HISTORIQUE DES ALERTES
+        // =====================================================
+        /**
+         * Récupère les dernières alertes d'un utilisateur
+         * @param {string} userId - ID de l'utilisateur
+         * @param {number} limit - Nombre max de résultats
+         * @returns {Promise<Array>} Historique des alertes
+         */
+        async getAlertHistory(userId, limit = 50) {
+            return adapter.getAlertHistory(userId, limit);
+        },
+
+        // =====================================================
+        // 5. CRÉER UNE NOUVELLE RÈGLE D'ALERTE
+        // =====================================================
+        /**
+         * Crée une règle d'alerte
+         * @param {Object} ruleData - Données de la règle
+         */
+        async createAlertRule(ruleData) {
+            return adapter.createAlertRule(ruleData);
+        }
+    };
+}
diff --git a/server/modules/alerts/alerts.router.js b/server/modules/alerts/alerts.router.js
new file mode 100644 (file)
index 0000000..8bfb49b
--- /dev/null
@@ -0,0 +1,74 @@
+// =========================================================
+// ALERTS ROUTER - VERSION RÉUTILISABLE
+// =========================================================
+// RÔLE : Définir les routes (endpoints) de l'API
+// =========================================================
+
+
+import express from 'express';
+
+// =========================================================
+// FACTORY FUNCTION : Créer un router
+// =========================================================
+/**
+ * Crée un router d'alertes réutilisable
+ *
+ * @param {Object} alertsController - Controller d'alertes (créé par createAlertsController)
+ *
+ * @returns {express.Router} Router Express configuré
+ */
+export function createAlertsRouter(alertsController) {
+
+    const router = express.Router();
+
+    console.log("Router d'alertes initialisé");
+
+// =========================================================
+    // DÉFINITION DES ROUTES
+// =========================================================
+
+// =============================================================================
+    // POST /api/alerts/process-signal
+// =============================================================================
+    /**
+     * Traiter un signal crypto et envoyer les alertes
+     *
+     * Exemple d'appel :
+     * POST http://localhost:3000/api/alerts/process-signal
+     * Body : {
+     *   "userId": "user-123",
+     *   "pairId": 1,
+     *   "pair": "BTC/EUR",
+     *   "action": "BUY",
+     *   "confidence": 0.85,
+     *   "criticality": "WARNING",
+     *   "reason": "RSI oversold + MACD crossover"
+     * }
+     */
+    router.post('/process-signal', alertsController.processSignal);
+
+// =============================================================================
+    // GET /api/alerts/rules/:userId
+// =============================================================================
+    /**
+     * Récupérer les règles d'alerte d'un utilisateur
+     *
+     * Exemple d'appel :
+     * GET http://localhost:3000/api/alerts/rules/user-123
+     */
+    router.get('/rules/:userId', alertsController.getRules);
+
+// =============================================================================
+    // GET /api/alerts/history/:userId
+// =============================================================================
+    /**
+    * Récupérer l'historique des alertes d'un utilisateur
+     *
+     * Exemple d'appel :
+     * GET http://localhost:3000/api/alerts/history/user-123?limit=20
+     */
+    router.get('/history/:userId', alertsController.getHistory);
+
+    return router;
+}
+
diff --git a/server/modules/alerts/alerts.service.js b/server/modules/alerts/alerts.service.js
new file mode 100644 (file)
index 0000000..c8d541e
--- /dev/null
@@ -0,0 +1,323 @@
+// =========================================================
+// ALERTS SERVICE - VERSION RÉUTILISABLE
+// =========================================================
+// RÔLE : Logique métier du système d'alertes
+// =========================================================
+// PRINCIPE : INJECTION DE DÉPENDANCES
+// Au lieu d'importer le Repository directement, on le reçoit en paramètre
+// =========================================================
+
+import { v4 as uuidv4 } from 'uuid';
+
+// Import des canaux
+import { sendAlertEmail } from './channels/mailer.js';
+import { sendConsoleAlert } from './channels/console.js';
+import { sendTelegramAlert } from './channels/telegram.js';
+import { sendDiscordAlert } from './channels/discord.js';
+import { sendWebAlert } from './channels/web.js';
+
+// =========================================================
+// FACTORY FUNCTION : Créer un service
+// =========================================================
+/**
+ * Crée un service d'alertes réutilisable
+ *
+ * @param {Object} alertsRepo - Repository d'alertes (créé par createAlertsRepo)
+ * @param {Object} options - Configuration optionnelle
+ * @param {number} options.defaultCooldown - Cooldown par défaut en ms (60000 = 1min)
+ *
+ * @returns {Object} Service avec toutes les méthodes
+ *
+ * @example
+ * // Dans Wall-e-tte
+ * import db from './config/db.js';
+ * import { createAlertsRepo } from './modules/alerts/alerts.repo.js';
+ * import { createAlertsService } from './modules/alerts/alerts.service.js';
+ *
+ * const repo = createAlertsRepo(db);
+ * const service = createAlertsService(repo);
+ *
+ * await service.processSignal(signal);
+ *
+ * @example
+ * // Dans un autre projet
+ * const repo = createAlertsRepo(strangersDb, { ... });
+ * const service = createAlertsService(repo);
+ * await service.processSignal(signal);  // Marche pareil !
+ */
+export function createAlertsService(alertsRepo, options = {}) {
+
+    console.log('🔧 Service d\'alertes initialisé');
+
+    // ─────────────────────────────────────────────────────
+    // RETOURNER L'OBJET SERVICE
+    // ─────────────────────────────────────────────────────
+    return {
+
+    // =====================================================
+    // 1. VÉRIFIER SI UNE ALERTE DOIT ÊTRE ENVOYÉE
+    // =====================================================
+    /**
+     * Détermine si une alerte doit être envoyée selon la règle
+     *
+     * Cette fonction applique les RÈGLES MÉTIER :
+     * - Vérification de la confidence minimum
+     * - Vérification du cooldown (anti-spam)
+     *
+     * @param {Object} rule - Règle d'alerte
+     * @param {Object} signal - Signal reçu
+     * @returns {boolean} true si l'alerte doit être envoyée
+     */
+    shouldSendAlert(rule, signal) {
+        console.log(`🔍 Vérification règle ${rule.rule_id}...`);
+
+        // ─────────────────────────────────────────────────
+        // CRITÈRE 1 : Vérifier la confidence minimum
+        // ─────────────────────────────────────────────────
+        // Si le signal a une confidence trop basse, on n'envoie pas
+        // Exemple : rule.min_confidence = 0.80 (80%)
+        //           signal.confidence = 0.75 (75%)
+        //           → Ne pas envoyer (75% < 80%)
+
+        if (signal.confidence < rule.min_confidence) {
+            console.log(`Confidence trop basse`);
+            console.log(`Signal : ${(signal.confidence * 100).toFixed(2)}%`);
+            console.log(`Minimum: ${(rule.min_confidence * 100).toFixed(2)}%`);
+            return false;
+        }
+
+        // ─────────────────────────────────────────────────
+        // CRITÈRE 2 : Vérifier le cooldown (anti-spam)
+        // ─────────────────────────────────────────────────
+        // Le cooldown évite d'envoyer 100 emails en 1 minute
+        // Exemple : cooldown_ms = 60000 (1 minute)
+        //           Dernière alerte envoyée il y a 30 secondes
+        //           → Trop tôt, ne pas envoyer
+
+        const now = Date.now();
+
+        if (rule.last_notified_at_ms) {
+            // Calculer le temps écoulé depuis la dernière alerte
+            const timeSinceLastAlert = now - rule.last_notified_at_ms;
+
+            // Si pas assez de temps écoulé, ne pas envoyer
+            if (timeSinceLastAlert < rule.cooldown_ms) {
+                const remainingMs = rule.cooldown_ms - timeSinceLastAlert;
+                const remainingSec = Math.ceil(remainingMs / 1000);
+
+                console.log(`   ⏳ Cooldown actif`);
+                console.log(`      Attendre encore ${remainingSec}s`);
+                return false;
+            }
+        }
+
+        // ─────────────────────────────────────────────────
+        // TOUS LES CRITÈRES SONT OK !
+        // ─────────────────────────────────────────────────
+        console.log(`   ✅ Tous les critères sont remplis`);
+        return true;
+    },
+
+    // =====================================================
+    // 2. ENVOYER UNE ALERTE VIA LE BON CANAL
+    // =====================================================
+    /**
+     * Envoie une alerte via le canal spécifié dans la règle
+     *
+     * Cette fonction :
+     * - Choisit la bonne fonction d'envoi (email, telegram, etc.)
+     * - Prépare les paramètres spécifiques au canal
+     * - Gère les erreurs d'envoi
+     *
+     * @param {Object} rule - Règle d'alerte avec le canal
+     * @param {Object} signal - Signal à envoyer
+     * @returns {Promise<string>} 'SENT' ou 'FAILED'
+     */
+    async sendViaChannel(rule, signal) {
+        console.log(`📡 Envoi via ${rule.channel}...`);
+
+        let status = 'SENT';
+
+        try {
+            // ─────────────────────────────────────────────
+            // SWITCH selon le canal configuré
+            // ─────────────────────────────────────────────
+            switch (rule.channel) {
+
+                // ── EMAIL ────────────────────────────────
+                case 'EMAIL':
+                    // Le destinataire est l'email de l'utilisateur
+                    // On l'a récupéré via le JOIN dans la requête SQL
+                    await sendAlertEmail(rule.email, signal);
+                    break;
+
+                // ── TELEGRAM ─────────────────────────────
+                case 'TELEGRAM':
+                    // Le chatId est stocké dans rule.params (JSON)
+                    // Exemple de params : {"chatId": "123456789"}
+                    const params = JSON.parse(rule.params);
+                    const chatId = params.chatId;
+
+                    if (!chatId) {
+                        console.error('❌ Pas de chatId dans params');
+                        status = 'FAILED';
+                        break;
+                    }
+
+                    await sendTelegramAlert(chatId, signal);
+                    break;
+
+                // ── DISCORD ──────────────────────────────
+                case 'DISCORD':
+                    const discordParams = JSON.parse(rule.params);
+                    const webhookUrl = discordParams.webhookUrl;
+
+                    if (!webhookUrl) {
+                        console.error('❌ Pas de webhookUrl dans params');
+                        status = 'FAILED';
+                        break;
+                    }
+
+                    await sendDiscordAlert(webhookUrl, signal);
+                    break;
+
+                // ── CONSOLE ──────────────────────────────
+                case 'CONSOLE':
+                    // Pas de paramètres nécessaires
+                    await sendConsoleAlert(signal);
+                    break;
+
+                // ── WEB ──────────────────────────────────
+                case 'WEB':
+                    // Envoyer à l'interface web de l'utilisateur
+                    await sendWebAlert(rule.user_id, signal);
+                    break;
+
+                // ── CANAL INCONNU ────────────────────────
+                default:
+                    console.warn(`⚠️ Canal inconnu: ${rule.channel}`);
+                    status = 'FAILED';
+            }
+
+        } catch (error) {
+            // ─────────────────────────────────────────────
+            // GESTION DES ERREURS
+            // ─────────────────────────────────────────────
+            console.error(`❌ Erreur lors de l'envoi via ${rule.channel}:`);
+            console.error(`   ${error.message}`);
+            status = 'FAILED';
+        }
+
+        return status;
+    },
+
+        // =====================================================
+        // 3. TRAITER UN SIGNAL ET ENVOYER LES ALERTES
+        // =====================================================
+        /**
+         * Fonction principale qui traite un signal crypto
+         *
+         * WORKFLOW :
+         * 1. Récupérer les règles actives pour ce signal
+         * 2. Pour chaque règle :
+         *    a. Vérifier si alerte doit être envoyée
+         *    b. Envoyer via le bon canal
+         *    c. Enregistrer dans l'historique
+         *    d. Mettre à jour le timestamp
+         *
+         * @param {Object} signal - Signal crypto reçu
+         * @param {string} signal.userId - ID utilisateur
+         * @param {number} signal.pairId - ID de la paire
+         * @param {string} signal.action - BUY, SELL, HOLD, STOP_LOSS
+         * @param {number} signal.confidence - 0-1
+         * @param {string} signal.criticality - CRITICAL, WARNING, INFO
+         * @param {string} signal.reason - Explication
+         */
+        async processSignal(signal) {
+            console.log('\n' + '═'.repeat(80));
+            console.log(`🔔 TRAITEMENT DU SIGNAL`);
+            console.log(`   Action : ${signal.action}`);
+            console.log(`   Paire  : ${signal.pair}`);
+            console.log(`   User   : ${signal.userId}`);
+            console.log('═'.repeat(80) + '\n');
+
+            try {
+                // ─────────────────────────────────────────────
+                // ÉTAPE 1 : Récupérer les règles actives
+                // ─────────────────────────────────────────────
+                // Utilise le repository injecté (pas d'import hardcodé)
+                const rules = await alertsRepo.findActiveRulesForSignal(
+                    signal.userId,
+                    signal.pairId
+                );
+
+                if (rules.length === 0) {
+                    console.log('⚠️ Aucune règle active trouvée pour ce signal');
+                    console.log('   → Vérifie que des règles sont configurées en DB\n');
+                    return;
+                }
+
+                console.log(`📋 ${rules.length} règle(s) trouvée(s)\n`);
+
+                // ─────────────────────────────────────────────
+                // ÉTAPE 2 : Traiter chaque règle
+                // ─────────────────────────────────────────────
+                let sentCount = 0;
+
+                for (const rule of rules) {
+                    console.log(`┌─ Règle: ${rule.rule_type} (${rule.channel})`);
+
+                    // Vérifier si on doit envoyer
+                    if (!this.shouldSendAlert(rule, signal)) {
+                        console.log(`└─ ❌ Alerte NON envoyée\n`);
+                        continue;
+                    }
+
+                    // Envoyer via le canal
+                    const status = await this.sendViaChannel(rule, signal);
+
+                    // Préparer les données de l'événement
+                    const eventData = {
+                        alert_event_id: uuidv4(),
+                        rule_id: rule.rule_id,
+                        timestamp_ms: Date.now(),
+                        severity: signal.criticality,
+                        channel: rule.channel,
+                        send_status: status,
+                        title: `${signal.action} ${signal.pair}`,
+                        message: signal.reason,
+                        signal_action: signal.action,
+                        confidence: signal.confidence,
+                        correlation_id: signal.correlationId || null
+                    };
+
+                    // Sauvegarder dans alert_events (via repo injecté)
+                    await alertsRepo.saveAlertEvent(eventData);
+
+                    // Mettre à jour last_notified_at si envoi réussi (via repo injecté)
+                    if (status === 'SENT') {
+                        await alertsRepo.updateLastNotified(rule.rule_id, Date.now());
+                        sentCount++;
+                        console.log(`└─ ✅ Alerte envoyée avec succès\n`);
+                    } else {
+                        console.log(`└─ ❌ Échec de l'envoi\n`);
+                    }
+                }
+
+                // ─────────────────────────────────────────────
+                // RÉSUMÉ FINAL
+                // ─────────────────────────────────────────────
+                console.log('═'.repeat(80));
+                console.log(`📊 RÉSUMÉ`);
+                console.log(`   Règles vérifiées : ${rules.length}`);
+                console.log(`   Alertes envoyées : ${sentCount}`);
+                console.log('═'.repeat(80) + '\n');
+
+            } catch (error) {
+                console.error('❌ ERREUR CRITIQUE dans processSignal:');
+                console.error(error);
+                throw error; // Remonter l'erreur pour que le controller puisse la gérer
+            }
+        }
+    };
+}
diff --git a/server/modules/alerts/channels/console.js b/server/modules/alerts/channels/console.js
new file mode 100644 (file)
index 0000000..c459871
--- /dev/null
@@ -0,0 +1,233 @@
+// =========================================================
+// CANAL CONSOLE - Notifications dans la console
+// =========================================================
+// RÔLE : Afficher les alertes dans le terminal
+// =========================================================
+// UTILITÉ :
+// - Développement et debugging
+// - Tests rapides sans configurer email/telegram
+// - Logs pour surveillance serveur
+// =========================================================
+
+// =========================================================
+// CODES COULEUR ANSI POUR LE TERMINAL (merci GPT)
+// =========================================================
+// Ces codes permettent de colorer le texte dans la console
+const COLORS = {
+    RESET: '\x1b[0m',
+
+    // Couleurs de texte
+    RED: '\x1b[31m',
+    GREEN: '\x1b[32m',
+    YELLOW: '\x1b[33m',
+    BLUE: '\x1b[34m',
+    MAGENTA: '\x1b[35m',
+    CYAN: '\x1b[36m',
+    WHITE: '\x1b[37m',
+
+    // Styles
+    BOLD: '\x1b[1m',
+    DIM: '\x1b[2m',
+
+    // Fond
+    BG_RED: '\x1b[41m',
+    BG_YELLOW: '\x1b[43m',
+    BG_BLUE: '\x1b[44m'
+};
+
+// =========================================================
+// FONCTION PRINCIPALE : Afficher une alerte dans la console
+// =========================================================
+/**
+ * Affiche une alerte formatée dans la console
+ *
+ * @param {Object} signal - Objet contenant les infos du signal
+ * @param {string} signal.action - BUY, SELL, HOLD, STOP_LOSS
+ * @param {string} signal.pair - Paire crypto (ex: BTC/EUR)
+ * @param {number} signal.confidence - Niveau de confiance (0-1)
+ * @param {string} signal.reason - Raison de l'alerte
+ * @param {string} signal.criticality - CRITICAL, WARNING, INFO
+ *
+ * @returns {Promise<string>} Toujours 'SENT' (console ne peut pas échouer)
+ */
+export async function sendConsoleAlert(signal) {
+
+    // =====================================================
+    // 1. DÉTERMINER LA COULEUR SELON LA CRITICITÉ
+    // =====================================================
+    let color;
+    let bgColor;
+    let icon;
+
+    switch (signal.criticality) {
+        case 'CRITICAL':
+            color = COLORS.RED;
+            bgColor = COLORS.BG_RED;
+            icon = '🚨';
+            break;
+        case 'WARNING':
+            color = COLORS.YELLOW;
+            bgColor = COLORS.BG_YELLOW;
+            icon = '⚠️';
+            break;
+        case 'INFO':
+        default:
+            color = COLORS.BLUE;
+            bgColor = COLORS.BG_BLUE;
+            icon = 'ℹ️';
+            break;
+    }
+
+    // =====================================================
+    // 2. FORMATER LA CONFIDENCE EN POURCENTAGE
+    // =====================================================
+    const confidencePercent = (parseFloat(signal.confidence) * 100).toFixed(2);
+
+    // =====================================================
+    // 3. CRÉER LE TIMESTAMP
+    // =====================================================
+    const timestamp = new Date().toLocaleString('fr-FR', {
+        day: '2-digit',
+        month: '2-digit',
+        year: 'numeric',
+        hour: '2-digit',
+        minute: '2-digit',
+        second: '2-digit'
+    });
+
+    // =====================================================
+    // 4. AFFICHER L'ALERTE AVEC MISE EN FORME
+    // =====================================================
+    console.log('\n'); // Ligne vide avant
+    console.log('═'.repeat(80)); // Ligne de séparation
+
+    // En-tête avec couleur de fond
+    console.log(
+        `${bgColor}${COLORS.WHITE}${COLORS.BOLD} ` +
+        `${icon} ALERTE ${signal.criticality} `.padEnd(80) +
+        `${COLORS.RESET}`
+    );
+
+    // Ligne de séparation
+    console.log('─'.repeat(80));
+
+    // Action recommandée (en couleur et gras)
+    console.log(
+        `${COLORS.BOLD}${color}ACTION :${COLORS.RESET} ` +
+        `${getActionEmoji(signal.action)} ${signal.action}`
+    );
+
+    // Paire crypto
+    console.log(
+        `${COLORS.BOLD}${COLORS.CYAN}PAIRE  :${COLORS.RESET} ` +
+        `${signal.pair}`
+    );
+
+    // Niveau de confiance avec barre visuelle
+    const confidenceBar = createProgressBar(signal.confidence);
+    console.log(
+        `${COLORS.BOLD}${COLORS.MAGENTA}CONFIANCE :${COLORS.RESET} ` +
+        `${confidenceBar} ${confidencePercent}%`
+    );
+
+    // Ligne de séparation
+    console.log('─'.repeat(80));
+
+    // Raison (analyse)
+    console.log(`${COLORS.BOLD}ANALYSE :${COLORS.RESET}`);
+    console.log(wrapText(signal.reason, 76)); // Wrap à 76 caractères
+
+    // Ligne de séparation
+    console.log('─'.repeat(80));
+
+    // Timestamp en grisé
+    console.log(`${COLORS.DIM}📅 ${timestamp}${COLORS.RESET}`);
+
+    // Ligne de fin
+    console.log('═'.repeat(80));
+    console.log('\n'); // Ligne vide après
+
+    // =====================================================
+    // 5. RETOURNER LE STATUT
+    // =====================================================
+    // La console ne peut jamais échouer, donc toujours SENT
+    return 'SENT';
+}
+
+// =========================================================
+// FONCTIONS UTILITAIRES
+// =========================================================
+
+/**
+ * Retourne l'emoji correspondant à l'action
+ */
+function getActionEmoji(action) {
+    const emojis = {
+        'BUY': '🟢',
+        'SELL': '🔴',
+        'HOLD': '🟡',
+        'STOP_LOSS': '🛑'
+    };
+    return emojis[action] || '📊';
+}
+
+/**
+ * Crée une barre de progression visuelle pour la confidence
+ * Exemple : ████████░░ (80%)
+ */
+function createProgressBar(confidence, length = 20) {
+    const filled = Math.round(confidence * length);
+    const empty = length - filled;
+
+    const bar =
+        COLORS.GREEN + '█'.repeat(filled) +
+        COLORS.DIM + '░'.repeat(empty) +
+        COLORS.RESET;
+
+    return `[${bar}]`;
+}
+
+/**
+ * Coupe le texte en plusieurs lignes si trop long
+ * Utile pour que la raison ne dépasse pas la largeur du terminal
+ */
+function wrapText(text, maxWidth) {
+    const words = text.split(' ');
+    const lines = [];
+    let currentLine = '  '; // Indentation
+
+    words.forEach(word => {
+        if ((currentLine + word).length > maxWidth) {
+            lines.push(currentLine);
+            currentLine = '  ' + word + ' ';
+        } else {
+            currentLine += word + ' ';
+        }
+    });
+
+    if (currentLine.trim()) {
+        lines.push(currentLine);
+    }
+
+    return lines.join('\n');
+}
+
+// =========================================================
+// EXPORT D'UNE FONCTION DE TEST
+// =========================================================
+/**
+ * Fonction pour tester rapidement le canal console
+ * Usage : node test-console.js
+ */
+export function testConsoleAlert() {
+    const fakeSignal = {
+        action: 'BUY',
+        pair: 'BTC/EUR',
+        confidence: 0.87,
+        criticality: 'WARNING',
+        reason: 'Les indicateurs techniques montrent une tendance haussière forte. Le RSI est à 45 (zone neutre), le MACD vient de croiser la ligne de signal vers le haut, et le volume des échanges augmente significativement.'
+    };
+
+    sendConsoleAlert(fakeSignal);
+}
+
diff --git a/server/modules/alerts/channels/discord.js b/server/modules/alerts/channels/discord.js
new file mode 100644 (file)
index 0000000..f3491d8
--- /dev/null
@@ -0,0 +1,23 @@
+// !!! A FAIRE !!!
+
+// =========================================================
+// CANAL DISCORD - Notifications via Discord Webhook
+// =========================================================
+// RÔLE : Envoyer des alertes dans un channel Discord
+// =========================================================
+
+/**
+ * Envoie une alerte via Discord Webhook
+ *
+ * @param {string} webhookUrl - URL du webhook Discord
+ * @param {Object} signal - Signal crypto
+ * @returns {Promise<string>} 'SENT' ou 'FAILED'
+ */
+export async function sendDiscordAlert(webhookUrl, signal) {
+    // TODO: À implémenter si nécessaire
+
+    console.log('💬 Canal Discord pas encore implémenté');
+
+    return 'FAILED';
+
+}
diff --git a/server/modules/alerts/channels/mailer.js b/server/modules/alerts/channels/mailer.js
new file mode 100644 (file)
index 0000000..1a4ebeb
--- /dev/null
@@ -0,0 +1,226 @@
+// =========================================================
+// CANAL EMAIL - Notifications par email
+// =========================================================
+// RÔLE : Envoyer des alertes par email avec Nodemailer
+// =========================================================
+
+import nodemailer from 'nodemailer';
+
+// =========================================================
+// FONCTION PRINCIPALE : Envoyer une alerte par email
+// =========================================================
+/**
+ * Envoie une alerte par email
+ *
+ * @param {string} to - Adresse email du destinataire
+ * @param {Object} signal - Objet contenant les infos du signal
+ * @param {string} signal.action - BUY, SELL, HOLD, STOP_LOSS
+ * @param {string} signal.pair - Paire crypto (ex: BTC/EUR)
+ * @param {number} signal.confidence - Niveau de confiance (0-1)
+ * @param {string} signal.reason - Raison de l'alerte
+ * @param {string} signal.criticality - CRITICAL, WARNING, INFO
+ *
+ * @returns {Promise<string>} 'SENT' ou 'FAILED'
+ */
+export async function sendAlertEmail(to, signal) {
+
+    // =====================================================
+    // 1. CRÉER LE TRANSPORTEUR SMTP
+    // =====================================================
+    // Le transporteur est l'objet qui envoie les emails
+    // Il se connecte au serveur SMTP (ex: Gmail, Mailtrap, etc.)
+    const transporter = nodemailer.createTransport({
+        host: process.env.MAIL_HOST,           // ex: smtp.gmail.com
+        port: parseInt(process.env.MAIL_PORT), // ex: 587
+        secure: process.env.MAIL_PORT === '465', // true pour le port 465, false pour les autres
+        auth: {
+            user: process.env.MAIL_USER,       // Ton adresse email
+            pass: process.env.MAIL_PASS        // Ton mot de passe ou App Password
+        }
+    });
+
+    try {
+        // =====================================================
+        // 2. FORMATER LES DONNÉES
+        // =====================================================
+        // Convertir la confidence en pourcentage
+        const confidencePercent = (parseFloat(signal.confidence) * 100).toFixed(2);
+
+        // Choisir l'emoji selon l'action
+        const emoji = getEmojiForAction(signal.action);
+
+        // Choisir la couleur selon la criticité
+        const color = getColorForCriticality(signal.criticality);
+
+        // =====================================================
+        // 3. CRÉER LE CONTENU DE L'EMAIL
+        // =====================================================
+        const mailOptions = {
+            from: `"Wall-e-tte Bot 🤖" <${process.env.MAIL_USER}>`,
+            to: to,
+            subject: `${emoji} Alerte ${signal.criticality} : ${signal.action} sur ${signal.pair}`,
+
+            // Version texte (pour clients email sans HTML)
+            text: `
+🚨 ALERTE CRYPTO 🚨
+
+Action recommandée : ${signal.action}
+Paire : ${signal.pair}
+Confiance : ${confidencePercent}%
+Criticité : ${signal.criticality}
+
+Raison :
+${signal.reason}
+
+---
+Wall-e-tte - Votre conseiller crypto
+            `.trim(),
+
+            // Version HTML (plus jolie)
+            html: `
+                <!DOCTYPE html>
+                <html>
+                <head>
+                    <style>
+                        body {
+                            font-family: Arial, sans-serif;
+                            background-color: #f4f4f4;
+                            margin: 0;
+                            padding: 0;
+                        }
+                        .container {
+                            max-width: 600px;
+                            margin: 20px auto;
+                            background-color: white;
+                            border-radius: 10px;
+                            overflow: hidden;
+                            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+                        }
+                        .header {
+                            background-color: ${color};
+                            color: white;
+                            padding: 20px;
+                            text-align: center;
+                        }
+                        .content {
+                            padding: 30px;
+                        }
+                        .alert-box {
+                            background-color: #f9f9f9;
+                            border-left: 4px solid ${color};
+                            padding: 15px;
+                            margin: 20px 0;
+                        }
+                        .footer {
+                            background-color: #333;
+                            color: white;
+                            text-align: center;
+                            padding: 15px;
+                            font-size: 12px;
+                        }
+                        .stat {
+                            display: inline-block;
+                            margin: 10px 20px;
+                        }
+                        .stat-label {
+                            color: #666;
+                            font-size: 12px;
+                            text-transform: uppercase;
+                        }
+                        .stat-value {
+                            font-size: 24px;
+                            font-weight: bold;
+                            color: ${color};
+                        }
+                    </style>
+                </head>
+                <body>
+                    <div class="container">
+                        <div class="header">
+                            <h1>${emoji} ALERTE ${signal.criticality}</h1>
+                        </div>
+                        <div class="content">
+                            <h2>Recommandation : ${signal.action}</h2>
+                            <p><strong>Paire :</strong> ${signal.pair}</p>
+
+                            <div class="stat">
+                                <div class="stat-label">Confiance</div>
+                                <div class="stat-value">${confidencePercent}%</div>
+                            </div>
+
+                            <div class="alert-box">
+                                <h3>Analyse :</h3>
+                                <p>${signal.reason}</p>
+                            </div>
+
+                            <p style="color: #666; font-size: 12px;">
+                                Timestamp : ${new Date().toLocaleString('fr-FR')}
+                            </p>
+                        </div>
+                        <div class="footer">
+                            Wall-e-tte - Votre conseiller crypto automatisé
+                        </div>
+                    </div>
+                </body>
+                </html>
+            `
+        };
+
+        // =====================================================
+        // 4. ENVOYER L'EMAIL
+        // =====================================================
+        const info = await transporter.sendMail(mailOptions);
+
+        console.log(`Email envoyé avec succès !`);
+        console.log(`   → Destinataire : ${to}`);
+        console.log(`   → Message ID : ${info.messageId}`);
+
+        return 'SENT';
+
+    } catch (error) {
+        // =====================================================
+        // 5. GESTION DES ERREURS
+        // =====================================================
+        console.error('Erreur lors de l\'envoi de l\'email :');
+        console.error(`   → ${error.message}`);
+
+        // Erreurs communes et solutions
+        if (error.message.includes('authentication')) {
+            console.error('   Vérifie MAIL_USER et MAIL_PASS dans .env');
+        } else if (error.message.includes('ECONNREFUSED')) {
+            console.error('   Vérifie MAIL_HOST et MAIL_PORT dans .env');
+        }
+
+        return 'FAILED';
+    }
+}
+
+// =========================================================
+// FONCTIONS UTILITAIRES
+// =========================================================
+
+/**
+ * Retourne un emoji selon l'action recommandée
+ */
+function getEmojiForAction(action) {
+    const emojis = {
+        'BUY': '🟢',
+        'SELL': '🔴',
+        'HOLD': '🟡',
+        'STOP_LOSS': '🛑'
+    };
+    return emojis[action] || '📊';
+}
+
+/**
+ * Retourne une couleur selon le niveau de criticité
+ */
+function getColorForCriticality(criticality) {
+    const colors = {
+        'CRITICAL': '#dc3545',  // Rouge
+        'WARNING': '#ffc107',   // Orange/Jaune
+        'INFO': '#17a2b8'       // Bleu
+    };
+    return colors[criticality] || '#6c757d';
+}
+
diff --git a/server/modules/alerts/channels/telegram.js b/server/modules/alerts/channels/telegram.js
new file mode 100644 (file)
index 0000000..ce3a74e
--- /dev/null
@@ -0,0 +1,55 @@
+// !!! À FAIRE !!!
+
+
+// =========================================================
+// CANAL TELEGRAM - Notifications via Telegram Bot
+// =========================================================
+// RÔLE : Envoyer des alertes via un bot Telegram
+// =========================================================
+
+// =========================================================
+// TODO : CONFIGURATION
+// =========================================================
+/*
+    Pour utiliser Telegram, il faut :
+
+    1. Créer un bot Telegram :
+        - Parler à @BotFather sur Telegram
+        - Utiliser /newbot
+        - Récupérer le TOKEN
+
+    2. Récupérer ton CHAT_ID :
+        - Parler à ton bot
+        - Aller sur : https://api.telegram.org/bot<TOKEN>/getUpdates
+        - Récupérer ton chat_id dans le JSON
+
+    3. Ajouter dans .env :
+        TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
+        TELEGRAM_CHAT_ID=123456789
+
+    4. Tester l'envoi :
+        - Utiliser fetch() ou axios
+        - POST vers https://api.telegram.org/bot<TOKEN>/sendMessage
+*/
+
+// =========================================================
+// FONCTION À IMPLÉMENTER
+// =========================================================
+/**
+ * Envoie une alerte via Telegram
+ *
+ * @param {string} chatId - ID du chat Telegram
+ * @param {Object} signal - Signal crypto
+ * @returns {Promise<string>} 'SENT' ou 'FAILED'
+ */
+export async function sendTelegramAlert(chatId, signal) {
+    // TODO: À implémenter ensemble
+
+    console.log('📱 Canal Telegram pas encore implémenté');
+    console.log(`   → chatId: ${chatId}`);
+    console.log(`   → signal: ${signal.action} sur ${signal.pair}`);
+
+    // Pour l'instant, on retourne FAILED
+    return 'FAILED';
+}
+
diff --git a/server/modules/alerts/channels/web.js b/server/modules/alerts/channels/web.js
new file mode 100644 (file)
index 0000000..d70c149
--- /dev/null
@@ -0,0 +1,76 @@
+// =========================================================
+// CANAL WEB - Notifications temps réel via Socket.IO
+// =========================================================
+// RÔLE : Envoyer des alertes en temps réel aux clients
+//        web (Océane) et mobile (Thibaud)
+// =========================================================
+// DÉPENDANCE : socketManager.js doit être initialisé
+// =========================================================
+
+import { sendAlertToUser, isUserConnected } from '../socketManager.js';
+
+/**
+ * Envoie une alerte via WebSocket à un utilisateur
+ *
+ * @param {string} userId - ID de l'utilisateur
+ * @param {Object} signal - Signal crypto à envoyer
+ * @param {string} signal.action - 'BUY', 'SELL', ou 'HOLD'
+ * @param {string} signal.pair - Paire crypto (ex: 'BTC/EUR')
+ * @param {number} signal.confidence - Niveau de confiance (0-1)
+ * @param {string} signal.reason - Raison du signal
+ * @param {string} [signal.criticality] - 'INFO', 'WARNING', 'CRITICAL'
+ * @returns {Promise<string>} 'SENT' ou 'FAILED'
+ * 
+ * @example
+ * const status = await sendWebAlert('user-123', {
+ *     action: 'BUY',
+ *     pair: 'BTC/EUR',
+ *     confidence: 0.85,
+ *     reason: 'RSI indique une survente',
+ *     criticality: 'WARNING'
+ * });
+ */
+export async function sendWebAlert(userId, signal) {
+    // Vérifier si l'utilisateur est connecté
+    if (!isUserConnected(userId)) {
+        console.log(`⚠️  [Web Channel] User ${userId} non connecté - alerte non envoyée`);
+        return 'FAILED';
+    }
+
+    // Formater l'alerte pour les clients
+    const alertPayload = {
+        // Données du signal
+        action: signal.action,
+        pair: signal.pair,
+        confidence: signal.confidence,
+        reason: signal.reason,
+        
+        // Métadonnées
+        alertLevel: signal.criticality || 'INFO',
+        timestamp: Date.now(),
+        
+        // Prix si disponible
+        ...(signal.priceAtSignal && { price: signal.priceAtSignal })
+    };
+
+    // Envoyer via Socket.IO
+    const sent = sendAlertToUser(userId, alertPayload);
+
+    if (sent) {
+        console.log(`✅ [Web Channel] Alerte envoyée à ${userId} : ${signal.action} ${signal.pair}`);
+        return 'SENT';
+    }
+
+    return 'FAILED';
+}
+
+/**
+ * Vérifie si le canal web est disponible pour un utilisateur
+ * (utile pour le service avant de tenter l'envoi)
+ * 
+ * @param {string} userId - ID de l'utilisateur
+ * @returns {boolean} true si l'utilisateur peut recevoir des alertes web
+ */
+export function isWebChannelAvailable(userId) {
+    return isUserConnected(userId);
+}
diff --git a/server/modules/alerts/index.js b/server/modules/alerts/index.js
new file mode 100644 (file)
index 0000000..f9bc531
--- /dev/null
@@ -0,0 +1,76 @@
+// =========================================================
+// MODULE ALERTS - Point d'entrée
+// =========================================================
+
+// Export des factory functions principales
+export { createAlertsRepo } from './alerts.repo.js';
+export { createAlertsService } from './alerts.service.js';
+export { createAlertsController } from './alerts.controller.js';
+export { createAlertsRouter } from './alerts.router.js';
+
+// Export des adapters (pour différentes bases de données)
+export { createMySQLAdapter } from './adapters/mysql.adapter.js';
+
+// Export du gestionnaire Socket.IO
+export {
+    initSocketIO,
+    sendAlertToUser,
+    broadcastAlert,
+    isUserConnected,
+    getConnectedUsersCount,
+    getI
+} from './socketManager.js';
+
+// Export des canaux (utiles si on veut les tester séparément)
+export { sendAlertEmail } from './channels/mailer.js';
+export { sendConsoleAlert } from './channels/console.js';
+export { sendTelegramAlert } from './channels/telegram.js';
+export { sendDiscordAlert } from './channels/discord.js';
+export { sendWebAlert } from './channels/web.js';
+
+// =========================================================
+// EXEMPLE D'UTILISATION RAPIDE
+// =========================================================
+/*
+    DANS WALL-E-TTE :
+
+    // 1. Import du module
+    import db from './config/db.js';
+    import {
+        createAlertsRepo,
+        createAlertsService,
+        createAlertsController,
+        createAlertsRouter
+    } from './modules/alerts/index.js';
+
+    // 2. Initialiser le module (dans l'ordre !)
+    const alertsRepo = createAlertsRepo(db);
+    const alertsService = createAlertsService(alertsRepo);
+    const alertsController = createAlertsController(alertsService, alertsRepo);
+    const alertsRouter = createAlertsRouter(alertsController);
+
+    // 3. Utiliser dans Express
+    app.use('/api/alerts', alertsRouter);
+
+    // 4. Ou utiliser directement le service
+    await alertsService.processSignal(mySignal);
+
+    ═══════════════════════════════════════════════════════
+
+    DANS UN AUTRE PROJET :
+
+    // Exactement pareil !
+    import myDb from './my-db-config.js';
+    import {
+        createAlertsRepo,
+        createAlertsService
+    } from '@wall-e-tte/alerts-module';
+
+    const repo = createAlertsRepo(myDb, {
+        alertsTable: 'my_notifications',
+        usersTable: 'my_users'
+    });
+    const service = createAlertsService(repo);
+
+    await service.processSignal(signal);  // Ça marche !
+*/
diff --git a/server/modules/alerts/init-alerts.js b/server/modules/alerts/init-alerts.js
new file mode 100644 (file)
index 0000000..42407ac
--- /dev/null
@@ -0,0 +1,159 @@
+// =========================================================
+// INITIALISATION DU MODULE ALERTS - VERSION AVEC ADAPTER
+// =========================================================
+// Ce fichier montre comment initialiser et utiliser le module d'alertes dans Wall-e-tte
+// =========================================================
+
+import db from '../config/db.js';
+import { createMySQLAdapter } from './alerts/adapters/mysql.adapter.js';
+import {
+    createAlertsRepo,
+    createAlertsService,
+    createAlertsController,
+    createAlertsRouter
+} from './alerts/index.js';
+
+// =========================================================
+// FONCTION D'INITIALISATION
+// =========================================================
+/**
+ * Initialise tout le module d'alertes
+ *
+ * @param {Object} adapter - Adapter de base de données (MySQL, MongoDB, etc.)
+ * @param {Object} options - Options de configuration
+ * @returns {Object} { adapter, repo, service, controller, router }
+ *
+ * @example
+ * // Avec MySQL (défaut pour Wall-e-tte)
+ * const alerts = initializeAlertsModule();
+ *
+ * @example
+ * // Avec un adapter personnalisé (autre projet)
+ * const mongoAdapter = createMongoAdapter(mongoClient);
+ * const alerts = initializeAlertsModule(mongoAdapter);
+ */
+export function initializeAlertsModule(adapter = null, options = {}) {
+
+    console.log('\n' + '═'.repeat(80));
+    console.log('INITIALISATION DU MODULE ALERTS (avec Adapter Pattern)');
+    console.log('═'.repeat(80) + '\n');
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 1 : Créer l'Adapter (si non fourni)
+    // ─────────────────────────────────────────────────────
+    // Par défaut, on utilise MySQL pour Wall-e-tte
+    // Mais un autre projet peut injecter son propre adapter
+    if (!adapter) {
+        console.log("Création de l'adapter MySQL par défaut...");
+        adapter = createMySQLAdapter(db, {
+            alertsTable: options.alertsTable || 'alert_rules',
+            usersTable: options.usersTable || 'users',
+            eventsTable: options.eventsTable || 'alert_events'
+        });
+    } else {
+        console.log('📦 Utilisation de l\'adapter fourni');
+    }
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 2 : Créer le Repository
+    // ─────────────────────────────────────────────────────
+    // Le repository utilise l'adapter
+    const alertsRepo = createAlertsRepo(adapter);
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 3 : Créer le Service
+    // ─────────────────────────────────────────────────────
+    // Le service contient la logique métier
+    const alertsService = createAlertsService(alertsRepo, {
+        defaultCooldown: options.defaultCooldown || 60000
+    });
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 4 : Créer le Controller
+    // ─────────────────────────────────────────────────────
+    // Le controller gère les requêtes HTTP
+    const alertsController = createAlertsController(alertsService, alertsRepo);
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 5 : Créer le Router
+    // ─────────────────────────────────────────────────────
+    // Le router définit les routes API
+    const alertsRouter = createAlertsRouter(alertsController);
+
+    console.log('✅ Module Alerts complètement initialisé !');
+    console.log('═'.repeat(80) + '\n');
+
+    // ─────────────────────────────────────────────────────
+    // RETOURNER TOUT
+    // ─────────────────────────────────────────────────────
+    return {
+        adapter: adapter,
+        repo: alertsRepo,
+        service: alertsService,
+        controller: alertsController,
+        router: alertsRouter
+    };
+}
+
+// =========================================================
+// EXPORT PAR DÉFAUT
+// =========================================================
+// Pour Wall-e-tte, initialiser avec la DB MySQL
+export default initializeAlertsModule();
+
+// =========================================================
+// EXEMPLE D'UTILISATION
+// =========================================================
+/*
+    ========================================================
+    UTILISATION DANS WALL-E-TTE
+    ========================================================
+
+    // Option 1 : Import par défaut (MySQL automatique)
+    import alerts from './modules/init-alerts.js';
+
+    app.use('/api/alerts', alerts.router);
+    await alerts.service.processSignal(signal);
+
+
+    // Option 2 : Configuration personnalisée
+    import { initializeAlertsModule } from './modules/init-alerts.js';
+
+    const alerts = initializeAlertsModule(null, {
+        alertsTable: 'mes_alertes',
+        defaultCooldown: 120000  // 2 minutes
+    });
+
+    =========================================================
+    UTILISATION DANS UN AUTRE PROJET (MySQL)
+    =========================================================
+
+    import theirDb from './their-db-config.js';
+    import { createMySQLAdapter } from '@wall-e-tte/alerts/adapters/mysql.adapter.js';
+    import { initializeAlertsModule } from '@wall-e-tte/alerts';
+
+    // Créer leur adapter avec leur DB
+    const adapter = createMySQLAdapter(theirDb, {
+        alertsTable: 'notifications',
+        usersTable: 'accounts'
+    });
+
+    // Initialiser avec leur adapter
+    const alerts = initializeAlertsModule(adapter);
+
+    app.use('/api/notifications', alerts.router);
+
+    =========================================================
+    UTILISATION AVEC MONGODB (autre projet)
+    =========================================================
+
+    import { MongoClient } from 'mongodb';
+    import { createMongoAdapter } from './adapters/mongo.adapter.js';  // À créer
+    import { initializeAlertsModule } from '@wall-e-tte/alerts';
+
+    const mongoClient = new MongoClient(uri);
+    const adapter = createMongoAdapter(mongoClient.db('alerts'));
+
+    const alerts = initializeAlertsModule(adapter);
+    // aucune modification du repo/service/controller/router
+*/
diff --git a/server/modules/alerts/socketManager.js b/server/modules/alerts/socketManager.js
new file mode 100644 (file)
index 0000000..576feb3
--- /dev/null
@@ -0,0 +1,194 @@
+// =========================================================
+// SOCKET MANAGER - Gestion des connexions WebSocket
+// =========================================================
+// RÔLE : Centraliser la gestion des connexions Socket.IO
+//        pour le module d'alertes
+// =========================================================
+// UTILISÉ PAR : web.js (canal de notification web)
+// =========================================================
+
+import { Server } from 'socket.io';
+
+// ─────────────────────────────────────────────────────────
+// STOCKAGE DES CONNEXIONS
+// ─────────────────────────────────────────────────────────
+// Map : userId → socket
+// Permet d'envoyer une alerte à un utilisateur spécifique
+const userSockets = new Map();
+
+// Instance du serveur Socket.IO
+let io = null;
+
+// ─────────────────────────────────────────────────────────
+// INITIALISATION DU SERVEUR SOCKET.IO
+// ─────────────────────────────────────────────────────────
+/**
+ * Initialise Socket.IO sur un serveur HTTP existant
+ * 
+ * @param {Object} httpServer - Serveur HTTP (Express)
+ * @param {Object} options - Options Socket.IO (optionnel)
+ * @returns {Server} Instance Socket.IO
+ * 
+ * @example
+ * // Dans le fichier principal du serveur (app.js ou index.js)
+ * import express from 'express';
+ * import { createServer } from 'http';
+ * import { initSocketIO } from './modules/alerts/socketManager.js';
+ * 
+ * const app = express();
+ * const httpServer = createServer(app);
+ * const io = initSocketIO(httpServer);
+ * 
+ * httpServer.listen(3000);
+ */
+export function initSocketIO(httpServer, options = {}) {
+    // Configuration par défaut + options personnalisées
+    const defaultOptions = {
+        cors: {
+            origin: "*", // En prod, restreindre aux domaines autorisés
+            methods: ["GET", "POST"]
+        }
+    };
+
+    io = new Server(httpServer, { ...defaultOptions, ...options });
+
+    // ─────────────────────────────────────────────────────
+    // GESTION DES CONNEXIONS
+    // ─────────────────────────────────────────────────────
+    io.on('connection', (socket) => {
+        console.log(`🔌 [Socket.IO] Nouvelle connexion : ${socket.id}`);
+
+        // ─────────────────────────────────────────────────
+        // EVENT : Authentification de l'utilisateur
+        // ─────────────────────────────────────────────────
+        // Le client doit envoyer son userId après connexion
+        socket.on('auth', (userId) => {
+            if (!userId) {
+                console.log(`⚠️  [Socket.IO] Auth sans userId (socket: ${socket.id})`);
+                return;
+            }
+
+            // Stocker la correspondance userId → socket
+            userSockets.set(userId, socket);
+            socket.userId = userId; // Garder une référence sur le socket
+
+            console.log(`✅ [Socket.IO] Utilisateur authentifié : ${userId}`);
+            console.log(`   Utilisateurs connectés : ${userSockets.size}`);
+
+            // Confirmer l'authentification au client
+            socket.emit('auth_success', { 
+                userId, 
+                message: 'Connecté au système d\'alertes' 
+            });
+        });
+
+        // ─────────────────────────────────────────────────
+        // EVENT : Déconnexion
+        // ─────────────────────────────────────────────────
+        socket.on('disconnect', (reason) => {
+            if (socket.userId) {
+                userSockets.delete(socket.userId);
+                console.log(`🔌 [Socket.IO] Déconnexion : ${socket.userId} (${reason})`);
+                console.log(`   Utilisateurs connectés : ${userSockets.size}`);
+            }
+        });
+
+        // ─────────────────────────────────────────────────
+        // EVENT : Ping (test de connexion)
+        // ─────────────────────────────────────────────────
+        socket.on('ping_alerts', () => {
+            socket.emit('pong_alerts', { 
+                timestamp: Date.now(),
+                status: 'ok' 
+            });
+        });
+    });
+
+    console.log('✅ [Socket.IO] Serveur initialisé');
+    return io;
+}
+
+// ─────────────────────────────────────────────────────────
+// FONCTIONS D'ENVOI D'ALERTES
+// ─────────────────────────────────────────────────────────
+
+/**
+ * Envoie une alerte à un utilisateur spécifique
+ * 
+ * @param {string} userId - ID de l'utilisateur cible
+ * @param {Object} alertData - Données de l'alerte
+ * @returns {boolean} true si envoyé, false si utilisateur non connecté
+ */
+export function sendAlertToUser(userId, alertData) {
+    const socket = userSockets.get(userId);
+
+    if (socket) {
+        socket.emit('alert', {
+            ...alertData,
+            timestamp: Date.now()
+        });
+        console.log(`📤 [Socket.IO] Alerte envoyée à ${userId}`);
+        return true;
+    }
+
+    console.log(`⚠️  [Socket.IO] Utilisateur ${userId} non connecté`);
+    return false;
+}
+
+/**
+ * Envoie une alerte à tous les utilisateurs connectés
+ * 
+ * @param {Object} alertData - Données de l'alerte
+ * @returns {number} Nombre d'utilisateurs notifiés
+ */
+export function broadcastAlert(alertData) {
+    if (!io) {
+        console.error('❌ [Socket.IO] Serveur non initialisé');
+        return 0;
+    }
+
+    io.emit('alert', {
+        ...alertData,
+        timestamp: Date.now()
+    });
+
+    console.log(`📢 [Socket.IO] Alerte broadcast à ${userSockets.size} utilisateurs`);
+    return userSockets.size;
+}
+
+// ─────────────────────────────────────────────────────────
+// FONCTIONS UTILITAIRES
+// ─────────────────────────────────────────────────────────
+
+/**
+ * Vérifie si un utilisateur est connecté
+ * @param {string} userId 
+ * @returns {boolean}
+ */
+export function isUserConnected(userId) {
+    return userSockets.has(userId);
+}
+
+/**
+ * Retourne le nombre d'utilisateurs connectés
+ * @returns {number}
+ */
+export function getConnectedUsersCount() {
+    return userSockets.size;
+}
+
+/**
+ * Retourne la liste des userIds connectés
+ * @returns {string[]}
+ */
+export function getConnectedUserIds() {
+    return Array.from(userSockets.keys());
+}
+
+/**
+ * Retourne l'instance Socket.IO (pour usage avancé)
+ * @returns {Server|null}
+ */
+export function getIO() {
+    return io;
+}
diff --git a/server/modules/alerts/test-alerts.js b/server/modules/alerts/test-alerts.js
new file mode 100644 (file)
index 0000000..0ad76cc
--- /dev/null
@@ -0,0 +1,164 @@
+// =========================================================
+// SCRIPT DE TEST - Module Alerts RÉUTILISABLE
+// =========================================================
+// Ce script teste ton module d'alertes avec la nouvelle
+// architecture réutilisable (injection de dépendances)
+// =========================================================
+// USAGE : node test-alerts.js
+// =========================================================
+
+import dotenv from 'dotenv';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+// Charger les variables d'environnement
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+// =========================================================
+// INITIALISATION DU MODULE
+// =========================================================
+import db from './config/db.js';
+import { createMySQLAdapter } from './modules/alerts/adapters/mysql.adapter.js';
+import { createAlertsRepo } from './modules/alerts/alerts.repo.js';
+import { createAlertsService } from './modules/alerts/alerts.service.js';
+
+// 1. Créer l'adapter MySQL avec la connexion DB
+const mysqlAdapter = createMySQLAdapter(db);
+
+// 2. Créer le repository avec l'adapter
+const alertsRepo = createAlertsRepo(mysqlAdapter);
+
+// 3. Créer le service avec le repository
+const alertsService = createAlertsService(alertsRepo);
+
+// =========================================================
+// FONCTION DE TEST PRINCIPALE
+// =========================================================
+async function runTest() {
+    console.log('\n' + '═'.repeat(80));
+    console.log('TEST DU MODULE ALERTS');
+    console.log('═'.repeat(80) + '\n');
+
+    try {
+        // =========================================================
+        // ÉTAPE 1 : Vérifier la connexion DB
+        // =========================================================
+        console.log('Test de connexion à la base de données\n');
+
+        // Utilise le repository créé avec injection de dépendances
+        const rules = await alertsRepo.findActiveRulesForSignal('test', 1);
+        console.log(`Connexion DB OK`);
+        console.log(`   Règles trouvées : ${rules.length}\n`);
+
+        if (rules.length === 0) {
+            console.log('ATTENTION : Aucune règle trouvée en DB');
+        }
+
+        // =========================================================
+        // ÉTAPE 2 : Test du canal CONSOLE
+        // =========================================================
+        console.log('─'.repeat(80));
+        console.log('Test du canal CONSOLE\n');
+
+        const { sendConsoleAlert } = await import('./modules/alerts/channels/console.js');
+
+        const testSignalConsole = {
+            action: 'BUY',
+            pair: 'BTC/EUR',
+            confidence: 0.87,
+            criticality: 'WARNING',
+            reason: 'Test du canal console : Les indicateurs techniques montrent une tendance haussière. Le RSI est à 45, le MACD vient de croiser.'
+        };
+
+        await sendConsoleAlert(testSignalConsole);
+        console.log('Test CONSOLE réussi\n');
+
+        // =========================================================
+        // ÉTAPE 3 : Test du canal EMAIL
+        // =========================================================
+        console.log('─'.repeat(80));
+        console.log('Test du canal EMAIL\n');
+
+        if (!process.env.MAIL_USER || !process.env.MAIL_PASS) {
+            console.log('Email non configuré (MAIL_USER et MAIL_PASS manquants dans .env)');
+            console.log('   Pour tester configurez vos variables dans .env\n');
+        } else {
+            console.log('Configuration email détectée');
+            console.log(`   Host : ${process.env.MAIL_HOST}`);
+            console.log(`   User : ${process.env.MAIL_USER}`);
+            console.log('   Envoi d\'un email de test...\n');
+
+            const { sendAlertEmail } = await import('./modules/alerts/channels/mailer.js');
+
+            const testSignalEmail = {
+                action: 'SELL',
+                pair: 'ETH/EUR',
+                confidence: 0.92,
+                criticality: 'CRITICAL',
+                reason: 'Test du canal email : Signal de vente critique détecté. Forte baisse imminente selon les indicateurs.'
+            };
+
+            const status = await sendAlertEmail(process.env.MAIL_USER, testSignalEmail);
+
+            if (status === 'SENT') {
+                console.log('Test EMAIL réussi ! Vérifiez votre boîte mail.\n');
+            } else {
+                console.log('Test EMAIL échoué. Vérifiez votre configuration.\n');
+            }
+        }
+
+        // =========================================================
+        // ÉTAPE 4 : Test du service complet
+        // =========================================================
+        if (rules.length > 0) {
+            console.log('─'.repeat(80));
+            console.log('Test du service complet\n');
+
+            const testSignalService = {
+                userId: rules[0].user_id,
+                pairId: rules[0].pair_id || 1,
+                pair: 'BTC/EUR',
+                action: 'BUY',
+                confidence: 0.85,
+                criticality: 'INFO',
+                reason: 'Test complet du service : Signal généré automatiquement pour tester le workflow complet.',
+                priceAtSignal: 45000.50
+            };
+
+            // Utilise le service créé avec injection de dépendances
+            await alertsService.processSignal(testSignalService);
+            console.log('Test SERVICE complet réussi !\n');
+        }
+
+        // =========================================================
+        // RÉSUMÉ FINAL
+        // =========================================================
+        console.log('═'.repeat(80));
+        console.log('TOUS LES TESTS SONT TERMINÉS');
+        console.log('═'.repeat(80));
+        console.log('\n RÉSUMÉ :');
+        console.log('   Connexion DB');
+        console.log('   Canal CONSOLE');
+        console.log(`   ${process.env.MAIL_USER ? 'OK : ' : 'FAIL : '} Canal EMAIL ${process.env.MAIL_USER ? '' : '(non configuré)'}`);
+        console.log(`   ${rules.length > 0 ? 'OK : ' : 'FAIL : '} Service complet ${rules.length > 0 ? '' : '(pas de règles en DB)'}`);
+
+    } catch (error) {
+        console.error('\n ERREUR LORS DU TEST :');
+        console.error(error);
+        console.error('\n VÉRIFICATIONS :');
+        console.error('   - Le fichier .env existe et contient les bonnes valeurs ?');
+        console.error('   - La base de données est démarrée ?');
+        console.error('   - Les tables sont créées (schema.sql) ?');
+        console.error('\n');
+    } finally {
+        // Quitter proprement
+        process.exit();
+    }
+}
+
+// =========================================================
+// LANCEMENT DU TEST
+// =========================================================
+runTest();
diff --git a/server/modules/init-alerts.js b/server/modules/init-alerts.js
new file mode 100644 (file)
index 0000000..1956182
--- /dev/null
@@ -0,0 +1,121 @@
+// =========================================================
+// INITIALISATION DU MODULE ALERTS
+// =========================================================
+// Ce fichier montre comment initialiser et utiliser
+// le module d'alertes dans Wall-e-tte
+// =========================================================
+
+import db from '../config/db.js';
+import {
+    createAlertsRepo,
+    createAlertsService,
+    createAlertsController,
+    createAlertsRouter
+} from './alerts/index.js';
+
+// =========================================================
+// FONCTION D'INITIALISATION
+// =========================================================
+/**
+ * Initialise tout le module d'alertes
+ *
+ * @param {Object} dbConnection - Connexion à la base de données
+ * @param {Object} options - Options de configuration
+ * @returns {Object} { repo, service, controller, router }
+ */
+export function initializeAlertsModule(dbConnection = db, options = {}) {
+
+    console.log('\n' + '═'.repeat(80)); // Pour creer une ligne de separation horizontale | /n pour saut de ligne
+    console.log('INITIALISATION DU MODULE ALERTS');
+    console.log('═'.repeat(80) + '\n');
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 1 : Créer le Repository
+    // ─────────────────────────────────────────────────────
+    // Le repository gère les requêtes SQL
+    const alertsRepo = createAlertsRepo(dbConnection, {
+        alertsTable: options.alertsTable || 'alert_rules',
+        usersTable: options.usersTable || 'users',
+        eventsTable: options.eventsTable || 'alert_events'
+    });
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 2 : Créer le Service
+    // ─────────────────────────────────────────────────────
+    // Le service contient la logique métier
+    const alertsService = createAlertsService(alertsRepo, {
+        defaultCooldown: options.defaultCooldown || 60000
+    });
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 3 : Créer le Controller
+    // ─────────────────────────────────────────────────────
+    // Le controller gère les requêtes HTTP
+    const alertsController = createAlertsController(alertsService, alertsRepo);
+
+    // ─────────────────────────────────────────────────────
+    // ÉTAPE 4 : Créer le Router
+    // ─────────────────────────────────────────────────────
+    // Le router définit les routes API
+    const alertsRouter = createAlertsRouter(alertsController);
+
+    console.log('✅ Module Alerts complètement initialisé !');
+    console.log('═'.repeat(80) + '\n');
+
+    // ─────────────────────────────────────────────────────
+    // RETOURNER TOUT
+    // ─────────────────────────────────────────────────────
+    return {
+        repo: alertsRepo,
+        service: alertsService,
+        controller: alertsController,
+        router: alertsRouter
+    };
+}
+
+// =========================================================
+// EXPORT PAR DÉFAUT
+// =========================================================
+// Pour Wall-e-tte, initialiser avec la DB par défaut
+export default initializeAlertsModule();
+
+// =========================================================
+// EXEMPLE D'UTILISATION
+// =========================================================
+/*
+    UTILISATION SIMPLE (dans Wall-e-tte) :
+
+    // Option 1 : Import par défaut (utilise la DB par défaut)
+    import alerts from './modules/init-alerts.js';
+
+    app.use('/api/alerts', alerts.router);
+    await alerts.service.processSignal(signal);
+
+================================================================================
+
+    // Option 2 : Import avec configuration personnalisée
+    import { initializeAlertsModule } from './modules/init-alerts.js';
+    import myDb from './my-db.js';
+
+    const alerts = initializeAlertsModule(myDb, {
+        alertsTable: 'mes_alertes',
+        defaultCooldown: 120000  // 2 minutes
+    });
+
+    app.use('/api/alerts', alerts.router);
+
+================================================================================
+
+    UTILISATION DANS UN AUTRE PROJET :
+
+    // Copier ce fichier et changer juste l'import de 'db'
+    import strangerDb from './stranger-db-config.js';
+    import {
+        createAlertsRepo,
+        createAlertsService
+    } from '@wall-e-tte/alerts';
+
+    const repo = createAlertsRepo(strangerDb);
+    const service = createAlertsService(repo);
+
+*/
diff --git a/server/package-lock.json b/server/package-lock.json
new file mode 100644 (file)
index 0000000..d7d6718
--- /dev/null
@@ -0,0 +1,989 @@
+{
+  "name": "wall-e-tte-alerts",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "wall-e-tte-alerts",
+      "version": "1.0.0",
+      "license": "ISC",
+      "dependencies": {
+        "dotenv": "^16.4.5",
+        "express": "^4.18.2",
+        "mysql2": "^3.6.5",
+        "nodemailer": "^6.9.7",
+        "uuid": "^9.0.1"
+      },
+      "devDependencies": {}
+    },
+    "node_modules/accepts": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-types": "~2.1.34",
+        "negotiator": "0.6.3"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+      "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+      "license": "MIT"
+    },
+    "node_modules/aws-ssl-profiles": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
+      "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/body-parser": {
+      "version": "1.20.4",
+      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
+      "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "~3.1.2",
+        "content-type": "~1.0.5",
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "~1.2.0",
+        "http-errors": "~2.0.1",
+        "iconv-lite": "~0.4.24",
+        "on-finished": "~2.4.1",
+        "qs": "~6.14.0",
+        "raw-body": "~2.5.3",
+        "type-is": "~1.6.18",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/bytes": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/call-bound": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "get-intrinsic": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/content-disposition": {
+      "version": "0.5.4",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "5.2.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/content-type": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+      "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+      "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie-signature": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+      "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/denque": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+      "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/depd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/destroy": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/dotenv": {
+      "version": "16.6.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+      "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://dotenvx.com"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+      "license": "MIT"
+    },
+    "node_modules/encodeurl": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "license": "MIT"
+    },
+    "node_modules/etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/express": {
+      "version": "4.22.1",
+      "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+      "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
+      "license": "MIT",
+      "dependencies": {
+        "accepts": "~1.3.8",
+        "array-flatten": "1.1.1",
+        "body-parser": "~1.20.3",
+        "content-disposition": "~0.5.4",
+        "content-type": "~1.0.4",
+        "cookie": "~0.7.1",
+        "cookie-signature": "~1.0.6",
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "~1.3.1",
+        "fresh": "~0.5.2",
+        "http-errors": "~2.0.0",
+        "merge-descriptors": "1.0.3",
+        "methods": "~1.1.2",
+        "on-finished": "~2.4.1",
+        "parseurl": "~1.3.3",
+        "path-to-regexp": "~0.1.12",
+        "proxy-addr": "~2.0.7",
+        "qs": "~6.14.0",
+        "range-parser": "~1.2.1",
+        "safe-buffer": "5.2.1",
+        "send": "~0.19.0",
+        "serve-static": "~1.16.2",
+        "setprototypeof": "1.2.0",
+        "statuses": "~2.0.1",
+        "type-is": "~1.6.18",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/finalhandler": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+      "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.4.1",
+        "parseurl": "~1.3.3",
+        "statuses": "~2.0.2",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/forwarded": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/generate-function": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+      "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+      "license": "MIT",
+      "dependencies": {
+        "is-property": "^1.0.2"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/http-errors": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+      "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+      "license": "MIT",
+      "dependencies": {
+        "depd": "~2.0.0",
+        "inherits": "~2.0.4",
+        "setprototypeof": "~1.2.0",
+        "statuses": "~2.0.2",
+        "toidentifier": "~1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "license": "MIT",
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "license": "ISC"
+    },
+    "node_modules/ipaddr.js": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/is-property": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+      "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
+      "license": "MIT"
+    },
+    "node_modules/long": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+      "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+      "license": "Apache-2.0"
+    },
+    "node_modules/lru.min": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz",
+      "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==",
+      "license": "MIT",
+      "engines": {
+        "bun": ">=1.0.0",
+        "deno": ">=1.30.0",
+        "node": ">=8.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wellwelwel"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/merge-descriptors": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+      "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "license": "MIT",
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "license": "MIT"
+    },
+    "node_modules/mysql2": {
+      "version": "3.17.0",
+      "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.17.0.tgz",
+      "integrity": "sha512-qF1KYPuytBGqAnMzaQ5/rW90iIqcjnrnnS7bvcJcdarJzlUTAiD9ZC0T7mwndacECseSQ6LcRbRvryXLp25m+g==",
+      "license": "MIT",
+      "dependencies": {
+        "aws-ssl-profiles": "^1.1.2",
+        "denque": "^2.1.0",
+        "generate-function": "^2.3.1",
+        "iconv-lite": "^0.7.2",
+        "long": "^5.3.2",
+        "lru.min": "^1.1.3",
+        "named-placeholders": "^1.1.6",
+        "seq-queue": "^0.0.5",
+        "sql-escaper": "^1.3.1"
+      },
+      "engines": {
+        "node": ">= 8.0"
+      }
+    },
+    "node_modules/mysql2/node_modules/iconv-lite": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+      "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+      "license": "MIT",
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/named-placeholders": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz",
+      "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==",
+      "license": "MIT",
+      "dependencies": {
+        "lru.min": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/negotiator": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/nodemailer": {
+      "version": "6.10.1",
+      "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz",
+      "integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==",
+      "license": "MIT-0",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.13.4",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+      "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/on-finished": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+      "license": "MIT",
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/path-to-regexp": {
+      "version": "0.1.12",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+      "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+      "license": "MIT"
+    },
+    "node_modules/proxy-addr": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+      "license": "MIT",
+      "dependencies": {
+        "forwarded": "0.2.0",
+        "ipaddr.js": "1.9.1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/qs": {
+      "version": "6.14.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
+      "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "side-channel": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/raw-body": {
+      "version": "2.5.3",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+      "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "~3.1.2",
+        "http-errors": "~2.0.1",
+        "iconv-lite": "~0.4.24",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "license": "MIT"
+    },
+    "node_modules/send": {
+      "version": "0.19.2",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+      "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "~0.5.2",
+        "http-errors": "~2.0.1",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "~2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "~2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/send/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "license": "MIT"
+    },
+    "node_modules/seq-queue": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
+      "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
+    },
+    "node_modules/serve-static": {
+      "version": "1.16.3",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+      "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
+      "license": "MIT",
+      "dependencies": {
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "~0.19.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "license": "ISC"
+    },
+    "node_modules/side-channel": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+      "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3",
+        "side-channel-list": "^1.0.0",
+        "side-channel-map": "^1.0.1",
+        "side-channel-weakmap": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-list": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+      "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-map": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+      "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-weakmap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+      "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3",
+        "side-channel-map": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/sql-escaper": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/sql-escaper/-/sql-escaper-1.3.1.tgz",
+      "integrity": "sha512-GLMJGWKzrr7BS5E5+8Prix6RGfBd4UokKMxkPSg313X0TvUyjdJU3Xg7FAhhcba4dHnLy81t4YeHETKLGVsDow==",
+      "license": "MIT",
+      "engines": {
+        "bun": ">=1.0.0",
+        "deno": ">=2.0.0",
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/mysqljs/sql-escaper?sponsor=1"
+      }
+    },
+    "node_modules/statuses": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+      "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/type-is": {
+      "version": "1.6.18",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+      "license": "MIT",
+      "dependencies": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.24"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/uuid": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+      "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "license": "MIT",
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    }
+  }
+}
diff --git a/server/package.json b/server/package.json
new file mode 100644 (file)
index 0000000..2c76723
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "name": "wall-e-tte-alerts",
+  "version": "1.0.0",
+  "description": "Module d'alertes et notifications pour Wall-e-tte",
+  "type": "module",
+  "main": "modules/alerts/alerts.service.js",
+  "scripts": {
+    "test": "node test-alerts.js"
+  },
+  "keywords": ["crypto", "alerts", "notifications", "wall-e-tte"],
+  "author": "Stéphane",
+  "license": "ISC",
+  "dependencies": {
+    "dotenv": "^16.4.5",
+    "express": "^4.18.2",
+    "mysql2": "^3.6.5",
+    "nodemailer": "^6.9.7",
+    "uuid": "^9.0.1"
+  },
+  "devDependencies": {}
+}
diff --git a/server/test-alerts.js b/server/test-alerts.js
new file mode 100644 (file)
index 0000000..2463776
--- /dev/null
@@ -0,0 +1,185 @@
+// =========================================================
+// SCRIPT DE TEST - Module Alerts RÉUTILISABLE
+// =========================================================
+// Ce script teste ton module d'alertes avec la nouvelle
+// architecture réutilisable (injection de dépendances)
+// =========================================================
+// USAGE : node test-alerts.js
+// =========================================================
+
+import dotenv from 'dotenv';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+// Charger les variables d'environnement
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+dotenv.config({ path: path.resolve(__dirname, '.env') });
+
+// =========================================================
+// INITIALISATION DU MODULE (nouvelle architecture !)
+// =========================================================
+import db from './config/db.js';
+import { createMySQLAdapter } from './modules/alerts/adapters/mysql.adapter.js';
+import { createAlertsRepo } from './modules/alerts/alerts.repo.js';
+import { createAlertsService } from './modules/alerts/alerts.service.js';
+
+// 1. Créer l'adapter MySQL avec la connexion DB
+const mysqlAdapter = createMySQLAdapter(db);
+
+// 2. Créer le repository avec l'adapter (plus de SQL dans le repo !)
+const alertsRepo = createAlertsRepo(mysqlAdapter);
+
+// 3. Créer le service avec le repository
+const alertsService = createAlertsService(alertsRepo);
+
+// =========================================================
+// FONCTION DE TEST PRINCIPALE
+// =========================================================
+async function runTest() {
+    console.log('\n' + '═'.repeat(80));
+    console.log('🧪 TEST DU MODULE ALERTS');
+    console.log('═'.repeat(80) + '\n');
+
+    try {
+        // ─────────────────────────────────────────────────
+        // ÉTAPE 1 : Vérifier la connexion DB
+        // ─────────────────────────────────────────────────
+        console.log('📊 ÉTAPE 1 : Test de connexion à la base de données\n');
+
+        // Utilise le repository créé avec injection de dépendances
+        const rules = await alertsRepo.findActiveRulesForSignal('test', 1);
+        console.log(`✅ Connexion DB OK`);
+        console.log(`   Règles trouvées : ${rules.length}\n`);
+
+        if (rules.length === 0) {
+            console.log('⚠️  ATTENTION : Aucune règle trouvée en DB');
+            console.log('   Pour tester complètement:');
+            console.log('   1. Créer un utilisateur dans la table users');
+            console.log('   2. Créer une règle dans la table alert_rules\n');
+            console.log('   Exemple de SQL :');
+            console.log(`
+                            INSERT INTO users (user_id, email, password_hash, display_name,
+                                                notify_on_hold, min_confidence_notify,
+                                                created_at_ms, updated_at_ms)
+                            VALUES ('test-user', 'test@example.com', 'hash', 'Test User',
+                                    0, 0.75,
+                                    UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000);
+
+                            INSERT INTO alert_rules (rule_id, user_id, pair_id, enabled,
+                                                        rule_type, severity, min_confidence,
+                                                        channel, params, cooldown_ms,
+                                                        created_at_ms, updated_at_ms)
+                            VALUES ('test-rule', 'test-user', 1, 1,
+                                    'SIGNAL_THRESHOLD', 'WARNING', 0.70,
+                                    'CONSOLE', '{}', 60000,
+                                    UNIX_TIMESTAMP()*1000, UNIX_TIMESTAMP()*1000);
+                                        `);
+
+            console.log('\n   tester les canaux !\n');
+        }
+
+        // ─────────────────────────────────────────────────
+        // ÉTAPE 2 : Test du canal CONSOLE
+        // ─────────────────────────────────────────────────
+        console.log('─'.repeat(80));
+        console.log('📺 ÉTAPE 2 : Test du canal CONSOLE\n');
+
+        const { sendConsoleAlert } = await import('./modules/alerts/channels/console.js');
+
+        const testSignalConsole = {
+            action: 'BUY',
+            pair: 'BTC/EUR',
+            confidence: 0.87,
+            criticality: 'WARNING',
+            reason: 'Test du canal console : Les indicateurs techniques montrent une tendance haussière. Le RSI est à 45, le MACD vient de croiser.'
+        };
+
+        await sendConsoleAlert(testSignalConsole);
+        console.log('✅ Test CONSOLE réussi\n');
+
+        // ─────────────────────────────────────────────────
+        // ÉTAPE 3 : Test du canal EMAIL (si configuré)
+        // ─────────────────────────────────────────────────
+        console.log('─'.repeat(80));
+        console.log('📧 ÉTAPE 3 : Test du canal EMAIL\n');
+
+        if (!process.env.MAIL_USER || !process.env.MAIL_PASS) {
+            console.log('⚠️  Email non configuré (MAIL_USER et MAIL_PASS manquants dans .env)');
+            console.log('   Pour tester l\'email, configure tes variables dans .env\n');
+        } else {
+            console.log('📬 Configuration email détectée');
+            console.log(`   Host : ${process.env.MAIL_HOST}`);
+            console.log(`   User : ${process.env.MAIL_USER}`);
+            console.log('   Envoi d\'un email de test...\n');
+
+            const { sendAlertEmail } = await import('./modules/alerts/channels/mailer.js');
+
+            const testSignalEmail = {
+                action: 'SELL',
+                pair: 'ETH/EUR',
+                confidence: 0.92,
+                criticality: 'CRITICAL',
+                reason: 'Test du canal email : Signal de vente critique détecté. Forte baisse imminente selon les indicateurs.'
+            };
+
+            const status = await sendAlertEmail(process.env.MAIL_TO || 'wallette@outlook.be', testSignalEmail);
+
+            if (status === 'SENT') {
+                console.log('✅ Test EMAIL réussi ! Vérifiez la boîte mail.\n');
+            } else {
+                console.log('❌ Test EMAIL échoué. Vérifiez la configuration.\n');
+            }
+        }
+
+        // ─────────────────────────────────────────────────
+        // ÉTAPE 4 : Test du service complet (si règles en DB)
+        // ─────────────────────────────────────────────────
+        if (rules.length > 0) {
+            console.log('─'.repeat(80));
+            console.log('🔄 ÉTAPE 4 : Test du service complet\n');
+
+            const testSignalService = {
+                userId: rules[0].user_id,
+                pairId: rules[0].pair_id || 1,
+                pair: 'BTC/EUR',
+                action: 'BUY',
+                confidence: 0.85,
+                criticality: 'INFO',
+                reason: 'Test complet du service : Signal généré automatiquement pour tester le workflow complet.',
+                priceAtSignal: 45000.50
+            };
+
+            // Utilise le service créé avec injection de dépendances
+            await alertsService.processSignal(testSignalService);
+            console.log('✅ Test SERVICE complet réussi !\n');
+        }
+
+        // ─────────────────────────────────────────────────
+        // RÉSUMÉ FINAL
+        // ─────────────────────────────────────────────────
+        console.log('═'.repeat(80));
+        console.log('✅ TOUS LES TESTS SONT TERMINÉS');
+        console.log('═'.repeat(80));
+        console.log('\n📋 RÉSUMÉ :');
+        console.log('   ✅ Connexion DB');
+        console.log('   ✅ Canal CONSOLE');
+        console.log(`   ${process.env.MAIL_USER ? '✅' : '⚠️ '} Canal EMAIL ${process.env.MAIL_USER ? '' : '(non configuré)'}`);
+        console.log(`   ${rules.length > 0 ? '✅' : '⚠️ '} Service complet ${rules.length > 0 ? '' : '(pas de règles en DB)'}`);
+    } catch (error) {
+        console.error('\n❌ ERREUR LORS DU TEST :');
+        console.error(error);
+        console.error('\n💡 VÉRIFICATIONS :');
+        console.error('   - Le fichier .env existe et contient les bonnes valeurs ?');
+        console.error('   - La base de données est démarrée ?');
+        console.error('   - Les tables sont créées (schema.sql) ?');
+        console.error('\n');
+    } finally {
+        // Quitter proprement
+        process.exit();
+    }
+}
+// =========================================================
+// LANCEMENT DU TEST
+// =========================================================
+runTest();
diff --git a/shémaGIT.png b/shémaGIT.png
new file mode 100644 (file)
index 0000000..931685e
Binary files /dev/null and "b/sh\303\251maGIT.png" differ
diff --git a/src/mocks/dashboard.mock.ts b/src/mocks/dashboard.mock.ts
deleted file mode 100644 (file)
index fa3d321..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-import { DashboardSummary } from "../types/DashboardSummary";
-
-export async function getDashboardSummary(): Promise<DashboardSummary> {
-  return {
-    pair: "BTC/EUR",
-    price: 42150.23,
-    strategy: "RSI_SIMPLE",
-    decision: "BUY",
-    confidence: 0.82,
-    reason: "RSI < 30, retournement haussier détecté",
-    timestamp: Date.now(),
-  };
-}
diff --git a/src/screens/DashboardScreen.tsx b/src/screens/DashboardScreen.tsx
deleted file mode 100644 (file)
index d632cfb..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-import { View, Text, StyleSheet, ScrollView, TouchableOpacity } from "react-native";
-import { useEffect, useState } from "react";
-import { DashboardSummary, TradeDecision } from "../types/DashboardSummary";
-import { fetchDashboardSummary } from "../services/dashboardService";
-import { SafeAreaView } from "react-native-safe-area-context";
-
-export default function DashboardScreen() {
-  const [summary, setSummary] = useState<DashboardSummary | null>(null);
-
-  useEffect(() => {
-    fetchDashboardSummary().then(setSummary);
-  }, []);
-
-  if (!summary) {
-    return (
-      <View style={styles.container}>
-        <Text>Chargement du dashboard…</Text>
-      </View>
-    );
-  }
-
-  const getDecisionColor = (decision: TradeDecision) => {
-    switch (decision) {
-      case "BUY":
-        return "#16a34a";
-      case "SELL":
-        return "#dc2626";
-      default:
-        return "#ca8a04";
-    }
-  };
-
-  return (
-  <SafeAreaView style={styles.safeArea}>
-    <ScrollView contentContainerStyle={styles.container}>
-      {/* Carte Marché */}
-      <View style={styles.card}>
-        <Text style={styles.sectionTitle}>Marché</Text>
-
-        <Text style={styles.price}>{summary.pair}</Text>
-
-        <View style={styles.priceRow}>
-          <Text style={styles.value}>Prix actuel</Text>
-          <Text style={styles.valueBold}>
-            {summary.price.toFixed(2)} €
-          </Text>
-        </View>
-
-        <Text style={styles.updated}>
-          Dernière mise à jour :{" "}
-          {new Date(summary.timestamp).toLocaleString()}
-        </Text>
-      </View>
-
-      {/* Carte Stratégie */}
-      <View style={styles.card}>
-        <Text style={styles.sectionTitle}>Stratégie</Text>
-
-        <Text style={styles.valueBold}>{summary.strategy}</Text>
-
-        <Text
-          style={[
-            styles.decision,
-            { color: getDecisionColor(summary.decision) },
-          ]}
-        >
-          {summary.decision}
-        </Text>
-
-        <View style={styles.priceRow}>
-          <Text style={styles.value}>Confiance</Text>
-          <Text style={styles.valueBold}>
-            {(summary.confidence * 100).toFixed(1)} %
-          </Text>
-        </View>
-
-        <Text style={styles.reason}>{summary.reason}</Text>
-      </View>
-
-      {/* Carte Portefeuille (Step 1 simplifié) */}
-      <View style={styles.card}>
-        <Text style={styles.sectionTitle}>Portefeuille</Text>
-
-        <View style={styles.priceRow}>
-          <Text style={styles.value}>Valeur totale</Text>
-          <Text style={styles.valueBold}>10 000 €</Text>
-        </View>
-
-        <Text style={styles.updated}>
-          Step 1 : mono-utilisateur / mono-crypto
-        </Text>
-      </View>
-
-      {/* Carte Actions */}
-      <View style={styles.card}>
-        <Text style={styles.sectionTitle}>Actions</Text>
-
-        <View style={styles.row}>
-          <TouchableOpacity style={styles.button}>
-            <Text style={styles.buttonText}>Voir stratégie</Text>
-          </TouchableOpacity>
-
-          <TouchableOpacity style={styles.button}>
-            <Text style={styles.buttonText}>Historique</Text>
-          </TouchableOpacity>
-        </View>
-      </View>
-    </ScrollView>
-    </SafeAreaView>
-  );
-}
-
-/* ===================== STYLES ===================== */
-
-const styles = StyleSheet.create({
-  container: {
-    padding: 16,
-  },
-
-  card: {
-    borderWidth: 1,
-    borderColor: "#aaa",
-    padding: 12,
-    marginBottom: 12,
-    borderRadius: 6,
-  },
-
-  sectionTitle: {
-    fontWeight: "bold",
-    marginBottom: 6,
-    fontSize: 16,
-  },
-
-  safeArea: {
-  flex: 1,
-  backgroundColor: "#fff",
-},
-
-  price: {
-    fontSize: 26,
-    fontWeight: "bold",
-    textAlign: "center",
-    marginVertical: 6,
-  },
-
-  decision: {
-    fontSize: 32,
-    fontWeight: "bold",
-    textAlign: "center",
-    marginVertical: 10,
-  },
-
-  row: {
-    flexDirection: "row",
-    justifyContent: "space-between",
-    alignItems: "center",
-  },
-
-  priceRow: {
-    flexDirection: "row",
-    justifyContent: "space-between",
-    alignItems: "center",
-    marginVertical: 4,
-  },
-
-  value: {
-    fontSize: 16,
-  },
-
-  valueBold: {
-    fontSize: 16,
-    fontWeight: "bold",
-  },
-
-  reason: {
-    marginTop: 6,
-    fontStyle: "italic",
-  },
-
-  button: {
-    backgroundColor: "#555",
-    paddingHorizontal: 10,
-    paddingVertical: 6,
-    borderRadius: 4,
-  },
-
-  buttonText: {
-    color: "#fff",
-    fontWeight: "bold",
-  },
-
-  updated: {
-    fontSize: 12,
-    opacity: 0.6,
-    marginTop: 6,
-    textAlign: "center",
-  },
-});
\ No newline at end of file
diff --git a/src/services/dashboardService.ts b/src/services/dashboardService.ts
deleted file mode 100644 (file)
index 3ee7bb0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-import { DashboardSummary } from "../types/DashboardSummary";
-import { getDashboardSummary } from "./mockApi";
-
-export async function fetchDashboardSummary(): Promise<DashboardSummary> {
-  return await getDashboardSummary();
-}
diff --git a/src/services/mockApi.ts b/src/services/mockApi.ts
deleted file mode 100644 (file)
index 3b3b889..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-import { DashboardSummary } from "../types/DashboardSummary";
-
-export const dashboardMock: DashboardSummary = {
-  pair: "BTC/EUR",
-  price: 42150.23,
-  strategy: "RSI_SIMPLE",
-  decision: "BUY",
-  confidence: 0.82,
-  reason: "RSI inférieur à 30 avec retournement haussier",
-  timestamp: Date.now(),
-};
-
-export const getDashboardSummary = async (): Promise<DashboardSummary> => {
-  // simulation d'appel API
-  return new Promise((resolve) => {
-    setTimeout(() => resolve(dashboardMock), 300);
-  });
-};
diff --git a/src/types/DashboardSummary.ts b/src/types/DashboardSummary.ts
deleted file mode 100644 (file)
index 461f66b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-export type TradeDecision = "BUY" | "SELL" | "HOLD";
-
-export interface DashboardSummary {
-  pair: string;        // ex: "BTC/EUR"
-  price: number;       // dernier close_price
-  strategy: string;    // user_strategies.strategy_key
-  decision: TradeDecision;
-  confidence: number;  // signals.confidence (0..1)
-  reason: string;      // signals.reason
-  timestamp: number;   // signals.timestamp_ms
-}
diff --git a/src/utils/settingsStorage.ts b/src/utils/settingsStorage.ts
deleted file mode 100644 (file)
index a623b96..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-import AsyncStorage from "@react-native-async-storage/async-storage";
-import type { UserSettings } from "../models/UserSettings";
-
-const KEY = "userSettings";
-
-const DEFAULT_SETTINGS: UserSettings = {
-  currency: "EUR",
-  favoriteSymbol: "BTC",
-  alertPreference: "critical",
-  refreshMode: "manual",
-};
-
-export async function loadSettings(): Promise<UserSettings> {
-  const raw = await AsyncStorage.getItem(KEY);
-  if (!raw) return DEFAULT_SETTINGS;
-
-  try {
-    const parsed = JSON.parse(raw) as Partial<UserSettings>;
-    return { ...DEFAULT_SETTINGS, ...parsed };
-  } catch {
-    return DEFAULT_SETTINGS;
-  }
-}
-
-export async function saveSettings(settings: UserSettings): Promise<void> {
-  await AsyncStorage.setItem(KEY, JSON.stringify(settings));
-}
diff --git a/system_notification/README.md b/system_notification/README.md
deleted file mode 100644 (file)
index 3216bcc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# system_notification
diff --git a/system_notification/config/db.js b/system_notification/config/db.js
deleted file mode 100644 (file)
index 38d1546..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-import mysql from 'mysql2/promise';
-import dotenv from 'dotenv';
-import path from 'path';
-import { fileURLToPath } from 'url';
-
-// On recrée __dirname qui n'existe pas en mode "module"
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// On charge le .env
-dotenv.config({ path: path.resolve(__dirname, '../.env') });
-
-const db = mysql.createPool({
-    host: process.env.DB_HOST,
-    port: process.env.DB_PORT,
-    user: process.env.DB_USER,
-    password: process.env.DB_PASS,
-    database: process.env.DB_NAME,
-    waitForConnections: true,
-    connectionLimit: 10,
-    queueLimit: 0
-});
-
-export default db;
diff --git a/system_notification/package-lock.json b/system_notification/package-lock.json
deleted file mode 100644 (file)
index d7d9d4b..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-{
-  "name": "system_notification",
-  "version": "1.0.0",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "system_notification",
-      "version": "1.0.0",
-      "license": "ISC",
-      "dependencies": {
-        "dotenv": "^17.2.4",
-        "mysql2": "^3.16.3",
-        "nodemailer": "^8.0.1"
-      }
-    },
-    "node_modules/aws-ssl-profiles": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
-      "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6.0.0"
-      }
-    },
-    "node_modules/denque": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
-      "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
-      "license": "Apache-2.0",
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/dotenv": {
-      "version": "17.2.4",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.4.tgz",
-      "integrity": "sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://dotenvx.com"
-      }
-    },
-    "node_modules/generate-function": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
-      "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "is-property": "^1.0.2"
-      }
-    },
-    "node_modules/iconv-lite": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
-      "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
-      "license": "MIT",
-      "dependencies": {
-        "safer-buffer": ">= 2.1.2 < 3.0.0"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/express"
-      }
-    },
-    "node_modules/is-property": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
-      "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
-      "license": "MIT"
-    },
-    "node_modules/long": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
-      "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
-      "license": "Apache-2.0"
-    },
-    "node_modules/lru.min": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz",
-      "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==",
-      "license": "MIT",
-      "engines": {
-        "bun": ">=1.0.0",
-        "deno": ">=1.30.0",
-        "node": ">=8.0.0"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wellwelwel"
-      }
-    },
-    "node_modules/mysql2": {
-      "version": "3.16.3",
-      "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.16.3.tgz",
-      "integrity": "sha512-+3XhQEt4FEFuvGV0JjIDj4eP2OT/oIj/54dYvqhblnSzlfcxVOuj+cd15Xz6hsG4HU1a+A5+BA9gm0618C4z7A==",
-      "license": "MIT",
-      "dependencies": {
-        "aws-ssl-profiles": "^1.1.2",
-        "denque": "^2.1.0",
-        "generate-function": "^2.3.1",
-        "iconv-lite": "^0.7.2",
-        "long": "^5.3.2",
-        "lru.min": "^1.1.3",
-        "named-placeholders": "^1.1.6",
-        "seq-queue": "^0.0.5",
-        "sqlstring": "^2.3.3"
-      },
-      "engines": {
-        "node": ">= 8.0"
-      }
-    },
-    "node_modules/named-placeholders": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz",
-      "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==",
-      "license": "MIT",
-      "dependencies": {
-        "lru.min": "^1.1.0"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/nodemailer": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.1.tgz",
-      "integrity": "sha512-5kcldIXmaEjZcHR6F28IKGSgpmZHaF1IXLWFTG+Xh3S+Cce4MiakLtWY+PlBU69fLbRa8HlaGIrC/QolUpHkhg==",
-      "license": "MIT-0",
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "license": "MIT"
-    },
-    "node_modules/seq-queue": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
-      "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
-    },
-    "node_modules/sqlstring": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
-      "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    }
-  }
-}
diff --git a/system_notification/package.json b/system_notification/package.json
deleted file mode 100644 (file)
index c123517..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "name": "system_notification",
-  "version": "1.0.0",
-  "type": "module",
-  "description": "",
-  "main": "test-connection.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
-  },
-  "keywords": [],
-  "author": "",
-  "license": "ISC",
-  "dependencies": {
-    "dotenv": "^17.2.4",
-    "mysql2": "^3.16.3",
-    "nodemailer": "^8.0.1"
-  }
-}
diff --git a/system_notification/repositories/MySqlAlertRepository.js b/system_notification/repositories/MySqlAlertRepository.js
deleted file mode 100644 (file)
index edebf2b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// 1. On importe la connexion à la base de données
-import db from '../config/db.js';
-
-const MySqlAlertRepository = {
-
-    /**
-     * Récupère toutes les règles d'alerte actives avec l'email de l'utilisateur
-     */
-    async findActiveRules() {
-        try {
-        // On prépare la requête SQL avec une jointure (JOIN)
-        // On récupère les colonnes de alert_rules (ar) et l'email de users (u)
-        const sql = `
-            SELECT ar.*, u.email
-            FROM alert_rules ar
-            JOIN users u ON ar.user_id = u.user_id
-            WHERE ar.enabled = 1
-        `;
-
-        // On exécute la requête
-        const [rows] = await db.execute(sql);
-
-        // On retourne les données
-        return rows;
-        } catch (error) {
-        console.error("Erreur dans findActiveRules:", error);
-        throw error; // On laisse le service gérer l'erreur si besoin
-        }
-    }
-
-
-};
-
-// 3. On exporte le repository
-export default MySqlAlertRepository;
diff --git a/system_notification/services/alerts/alertServices.js b/system_notification/services/alerts/alertServices.js
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/system_notification/services/channels/discord.js b/system_notification/services/channels/discord.js
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/system_notification/services/channels/mailer.js b/system_notification/services/channels/mailer.js
deleted file mode 100644 (file)
index b255c95..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-import nodemailer from 'nodemailer';
-
-
-export async function sendAlertEmail(to, signal) {
-    const transporter = nodemailer.createTransport({
-        host: process.env.MAIL_HOST,
-        port: parseInt(process.env.MAIL_PORT),
-        auth: {
-            user: process.env.MAIL_USER,
-            pass: process.env.MAIL_PASS
-        }
-    });
-
-    try {
-        const confidencePercent = (parseFloat(signal.confidence) * 100).toFixed(2);
-        const mailOptions = {
-            from: `"Wall-e-tte" <${process.env.MAIL_USER}>`,
-            to: to,
-            subject: `🚨 Alerte : ${signal.action} sur ${signal.pair}`,
-            text: `Action : ${signal.action}\nConfiance : ${confidencePercent}%`,
-        };
-
-        const info = await transporter.sendMail(mailOptions);
-        console.log("✅ Email envoyé ! ID:", info.messageId);
-        return 'SENT';
-    } catch (error) {
-        console.error("❌ Erreur d'envoi mail :", error.message);
-        return 'FAILED';
-    }
-}
-
-
diff --git a/system_notification/services/channels/telegram.js b/system_notification/services/channels/telegram.js
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/system_notification/services/channels/web.js b/system_notification/services/channels/web.js
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/system_notification/test-connection.js b/system_notification/test-connection.js
deleted file mode 100644 (file)
index da2b741..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-import repository from './repositories/MySqlAlertRepository.js'; // Note le .js obligatoire !
-
-async function test() {
-    console.log("Tentative de connexion à MariaDB...");
-
-    try {
-        const rules = await repository.findActiveRules();
-        console.log("✅ Connexion réussie !");
-        console.log(`📊 Nombre de règles actives trouvées : ${rules.length}`);
-
-        if (rules.length > 0) {
-            console.log("Détail de la première règle :", rules[0]);
-        } else {
-            console.log("La connexion marche, mais la table 'alert_rules' est vide.");
-        }
-
-    } catch (error) {
-        console.error("❌ ÉCHEC du test :");
-        console.error("Détail de l'erreur :", error.message);
-    } finally {
-        process.exit();
-    }
-}
-
-test();
diff --git a/system_notification/test-mailer.js b/system_notification/test-mailer.js
deleted file mode 100644 (file)
index 7f6670c..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-import dotenv from 'dotenv';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import repository from './repositories/MySqlAlertRepository.js';
-import { sendAlertEmail } from './services/channels/mailer.js';
-
-// Configuration nécessaire pour retrouver __dirname en mode "import"
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// Chargement des variables d'environnement
-dotenv.config({ path: path.resolve(__dirname, '.env') });
-
-async function runTest() {
-    console.log("🔍 Recherche d'une règle active dans la DB...");
-
-    try {
-        const rules = await repository.findActiveRules();
-
-        if (rules.length === 0) {
-            console.log("⚠️ Aucune règle trouvée. Vérifie tes tables SQL.");
-            return;
-        }
-
-        const rule = rules[0];
-        console.log(`✅ Règle trouvée pour : ${rule.email}`);
-
-        // On simule un signal de test
-        const fakeSignal = {
-            action: 'BUY',
-            pair: 'BTC/EUR',
-            confidence: 0.85,
-            severity: 'WARNING'
-        };
-
-        console.log("✉️ Tentative d'envoi du mail...");
-
-        // Appel direct de la fonction importée (plus de require ici !)
-        const status = await sendAlertEmail(rule.email, fakeSignal);
-
-        console.log(`📊 Résultat de l'envoi : ${status}`);
-
-    } catch (error) {
-        console.error("❌ Erreur pendant le test :", error);
-    } finally {
-        process.exit();
-    }
-}
-
-runTest();
diff --git a/tsconfig.json b/tsconfig.json
deleted file mode 100644 (file)
index b9567f6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "extends": "expo/tsconfig.base",
-  "compilerOptions": {
-    "strict": true
-  }
-}