From 49fd6f30e91e1a91d35cce5118c4b2829ac6c56a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 17:35:25 +0000
Subject: [PATCH 01/13] feat: implement Evodron Referral Program (backend,
frontend, tests)
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
.gitignore | 4 +
app.js | 41 +
package-lock.json | 5307 ++++++++++++++++++++++++++++++++++++++
package.json | 23 +
public/css/style.css | 184 ++
public/dashboard.html | 85 +
public/index.html | 45 +
public/js/referral.js | 117 +
public/login.html | 66 +
public/referral.html | 96 +
public/register.html | 89 +
src/config/rewards.js | 58 +
src/db/database.js | 30 +
src/db/schema.sql | 59 +
src/middleware/auth.js | 38 +
src/models/referral.js | 80 +
src/models/reward.js | 58 +
src/models/user.js | 53 +
src/routes/auth.js | 93 +
src/routes/referral.js | 119 +
tests/anti-abuse.test.js | 137 +
tests/referral.test.js | 196 ++
22 files changed, 6978 insertions(+)
create mode 100644 .gitignore
create mode 100644 app.js
create mode 100644 package-lock.json
create mode 100644 package.json
create mode 100644 public/css/style.css
create mode 100644 public/dashboard.html
create mode 100644 public/index.html
create mode 100644 public/js/referral.js
create mode 100644 public/login.html
create mode 100644 public/referral.html
create mode 100644 public/register.html
create mode 100644 src/config/rewards.js
create mode 100644 src/db/database.js
create mode 100644 src/db/schema.sql
create mode 100644 src/middleware/auth.js
create mode 100644 src/models/referral.js
create mode 100644 src/models/reward.js
create mode 100644 src/models/user.js
create mode 100644 src/routes/auth.js
create mode 100644 src/routes/referral.js
create mode 100644 tests/anti-abuse.test.js
create mode 100644 tests/referral.test.js
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..5f7e2b7f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+node_modules/
+evodron.db
+*.db
+.env
diff --git a/app.js b/app.js
new file mode 100644
index 00000000..9b48f3cc
--- /dev/null
+++ b/app.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const express = require('express');
+const cookieParser = require('cookie-parser');
+const path = require('path');
+
+const authRoutes = require('./src/routes/auth');
+const referralRoutes = require('./src/routes/referral');
+
+const app = express();
+const PORT = process.env.PORT || 3000;
+
+// Middleware
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+
+// Serve static frontend files
+app.use(express.static(path.join(__dirname, 'public')));
+
+// API routes
+app.use('/api/auth', authRoutes);
+app.use('/api/referral', referralRoutes);
+
+// Catch-all: serve index.html for client-side navigation
+app.get('*', (req, res) => {
+ res.sendFile(path.join(__dirname, 'public', 'index.html'));
+});
+
+// Only start listening when run directly (not during tests)
+if (require.main === module) {
+ if (!process.env.JWT_SECRET) {
+ console.error('ERROR: JWT_SECRET environment variable is not set. Refusing to start.');
+ process.exit(1);
+ }
+ app.listen(PORT, () => {
+ console.log(`Evodron Referral server running on http://localhost:${PORT}`);
+ });
+}
+
+module.exports = app;
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..c19cdd83
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,5307 @@
+{
+ "name": "evodron-referral",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "evodron-referral",
+ "version": "1.0.0",
+ "dependencies": {
+ "bcryptjs": "^2.4.3",
+ "better-sqlite3": "^9.4.3",
+ "cookie-parser": "^1.4.6",
+ "express": "^4.18.2",
+ "jsonwebtoken": "^9.0.2",
+ "nanoid": "^3.3.7"
+ },
+ "devDependencies": {
+ "jest": "^29.7.0",
+ "supertest": "^6.3.4"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
+ "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
+ "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.7",
+ "@babel/helper-compilation-targets": "^7.29.7",
+ "@babel/helper-module-transforms": "^7.29.7",
+ "@babel/helpers": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/template": "^7.29.7",
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7",
+ "@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/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@babel/core/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
+ "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.8",
+ "@babel/types": "^7.29.8",
+ "@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-compilation-targets": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+ "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.29.7",
+ "@babel/helper-validator-option": "^7.29.7",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+ "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+ "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+ "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "@babel/traverse": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+ "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+ "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+ "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
+ "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
+ "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.8"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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-import-attributes": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz",
+ "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
+ "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
+ "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
+ "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/parser": "^7.29.7",
+ "@babel/types": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
+ "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.7",
+ "@babel/generator": "^7.29.8",
+ "@babel/helper-globals": "^7.29.7",
+ "@babel/parser": "^7.29.8",
+ "@babel/template": "^7.29.7",
+ "@babel/types": "^7.29.8",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@babel/traverse/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
+ "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.29.7",
+ "@babel/helper-validator-identifier": "^7.29.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@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==",
+ "dev": true,
+ "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/schema": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz",
+ "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "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==",
+ "dev": true,
+ "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/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "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==",
+ "dev": true,
+ "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/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "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==",
+ "dev": true,
+ "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/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "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/@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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
+ "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "^1.1.5"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.12",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz",
+ "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "26.2.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
+ "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~8.3.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "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/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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==",
+ "dev": true,
+ "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-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==",
+ "dev": true,
+ "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-istanbul/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==",
+ "dev": true,
+ "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/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==",
+ "dev": true,
+ "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-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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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.11.13",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz",
+ "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
+ "license": "MIT"
+ },
+ "node_modules/better-sqlite3": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.6.0.tgz",
+ "integrity": "sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "prebuild-install": "^7.1.1"
+ }
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.6",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz",
+ "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==",
+ "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.15.1",
+ "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/brace-expansion": {
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
+ "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.8",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz",
+ "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==",
+ "dev": true,
+ "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": {
+ "baseline-browser-mapping": "^2.11.12",
+ "caniuse-lite": "^1.0.30001809",
+ "electron-to-chromium": "^1.5.402",
+ "node-releases": "^2.0.53",
+ "update-browserslist-db": "^1.3.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==",
+ "dev": true,
+ "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-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "dev": true,
+ "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/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/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001809",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz",
+ "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==",
+ "dev": true,
+ "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": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "license": "ISC"
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/component-emitter": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
+ "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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-parser": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
+ "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "0.7.2",
+ "cookie-signature": "1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/cookiejar": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
+ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "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/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/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/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dezalgo": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "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.404",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.404.tgz",
+ "integrity": "sha512-3WJtd7/lVq2Jnuz6wed1l9+1ZD2u2Tet1/1NBc4Iedkmgbu+I7YuAqdAQ8T+VZtnwysMsAf3IqSq9D1gyZjA2g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "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.2",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+ "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "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": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "license": "(MIT OR WTFPL)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.22.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
+ "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "~1.20.5",
+ "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.15.1",
+ "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/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "license": "MIT"
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
+ "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.4",
+ "mime-types": "^2.1.35"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/formidable": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz",
+ "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@paralleldrive/cuid2": "^2.2.2",
+ "dezalgo": "^1.0.4",
+ "once": "^1.4.0",
+ "qs": "^6.11.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
+ }
+ },
+ "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/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "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-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "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/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "license": "MIT"
+ },
+ "node_modules/glob": {
+ "version": "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",
+ "dev": true,
+ "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/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/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-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/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/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/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/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/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.",
+ "dev": true,
+ "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/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-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "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-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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-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==",
+ "dev": true,
+ "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/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "3.15.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz",
+ "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonwebtoken": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
+ "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
+ "license": "MIT",
+ "dependencies": {
+ "jws": "^4.0.1",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jsonwebtoken/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/jsonwebtoken/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "license": "MIT"
+ },
+ "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==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "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/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "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/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/napi-build-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
+ "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/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/node-abi": {
+ "version": "3.94.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz",
+ "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-abi/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.53",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz",
+ "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/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/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
+ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
+ "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
+ "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^2.0.0",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/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/pump": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
+ "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/qs": {
+ "version": "6.15.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
+ "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "es-define-property": "^1.0.1",
+ "side-channel": "^1.1.1"
+ },
+ "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/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "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-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/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/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/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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4",
+ "side-channel-list": "^1.0.1",
+ "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.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
+ },
+ "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/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/superagent": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz",
+ "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==",
+ "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "component-emitter": "^1.3.0",
+ "cookiejar": "^2.1.4",
+ "debug": "^4.3.4",
+ "fast-safe-stringify": "^2.1.1",
+ "form-data": "^4.0.0",
+ "formidable": "^2.1.2",
+ "methods": "^1.1.2",
+ "mime": "2.6.0",
+ "qs": "^6.11.0",
+ "semver": "^7.3.8"
+ },
+ "engines": {
+ "node": ">=6.4.0 <13 || >=14"
+ }
+ },
+ "node_modules/superagent/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/superagent/node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/superagent/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/superagent/node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/supertest": {
+ "version": "6.3.4",
+ "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz",
+ "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==",
+ "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "methods": "^1.1.2",
+ "superagent": "^8.1.2"
+ },
+ "engines": {
+ "node": ">=6.4.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
+ "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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/undici-types": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
+ "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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.3.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz",
+ "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==",
+ "dev": true,
+ "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/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.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/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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/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==",
+ "dev": true,
+ "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/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..5a1aa746
--- /dev/null
+++ b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "evodron-referral",
+ "version": "1.0.0",
+ "description": "Evodron Referral Program — backend and frontend",
+ "main": "app.js",
+ "scripts": {
+ "start": "node app.js",
+ "dev": "node app.js",
+ "test": "jest --testPathPattern=tests/"
+ },
+ "dependencies": {
+ "bcryptjs": "^2.4.3",
+ "better-sqlite3": "^9.4.3",
+ "cookie-parser": "^1.4.6",
+ "express": "^4.18.2",
+ "jsonwebtoken": "^9.0.2",
+ "nanoid": "^3.3.7"
+ },
+ "devDependencies": {
+ "jest": "^29.7.0",
+ "supertest": "^6.3.4"
+ }
+}
diff --git a/public/css/style.css b/public/css/style.css
new file mode 100644
index 00000000..4fa63942
--- /dev/null
+++ b/public/css/style.css
@@ -0,0 +1,184 @@
+/* ── Evodron Referral — Stylesheet ───────────────────────────────────── */
+
+:root {
+ --color-bg: #0f1117;
+ --color-surface: #1a1d27;
+ --color-border: #2a2d3a;
+ --color-primary: #6e56cf;
+ --color-primary-h: #7d68d8;
+ --color-success: #22c55e;
+ --color-error: #ef4444;
+ --color-text: #e2e8f0;
+ --color-muted: #8892a4;
+ --radius: 10px;
+ --font: 'Segoe UI', system-ui, sans-serif;
+}
+
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+
+body {
+ background: var(--color-bg);
+ color: var(--color-text);
+ font-family: var(--font);
+ font-size: 15px;
+ line-height: 1.6;
+ min-height: 100vh;
+}
+
+a { color: var(--color-primary); text-decoration: none; }
+a:hover { text-decoration: underline; }
+
+/* ── Layout ── */
+.container { max-width: 820px; margin: 0 auto; padding: 0 1.25rem; }
+
+/* ── Header ── */
+.site-header {
+ background: var(--color-surface);
+ border-bottom: 1px solid var(--color-border);
+ padding: .75rem 0;
+}
+.site-header .container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.site-header nav { display: flex; gap: .5rem; align-items: center; }
+.logo { font-size: 1.25rem; font-weight: 700; color: var(--color-text); }
+
+/* ── Buttons ── */
+.btn {
+ display: inline-flex;
+ align-items: center;
+ gap: .4rem;
+ padding: .45rem 1rem;
+ border: none;
+ border-radius: var(--radius);
+ font-size: .9rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background .15s, opacity .15s;
+ text-decoration: none;
+}
+.btn-primary { background: var(--color-primary); color: #fff; }
+.btn-primary:hover { background: var(--color-primary-h); }
+.btn-secondary { background: var(--color-surface); color: var(--color-text); border: 1px solid var(--color-border); }
+.btn-secondary:hover { background: var(--color-border); }
+.btn-ghost { background: transparent; color: var(--color-muted); border: 1px solid var(--color-border); }
+.btn-ghost:hover { color: var(--color-text); }
+.btn-large { padding: .7rem 1.6rem; font-size: 1rem; }
+.btn-block { width: 100%; justify-content: center; }
+.btn-sm { padding: .3rem .7rem; font-size: .8rem; }
+
+/* ── Hero ── */
+.hero { padding: 5rem 0 3rem; text-align: center; }
+.hero h2 { font-size: 2.2rem; margin-bottom: 1rem; }
+.hero p { color: var(--color-muted); font-size: 1.1rem; margin-bottom: 2rem; }
+.hero-content { display: flex; flex-direction: column; align-items: center; gap: .75rem; }
+
+/* ── Cards ── */
+.card {
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius);
+ padding: 1.5rem;
+ margin-bottom: 1.25rem;
+}
+.card h3 { font-size: 1.1rem; margin-bottom: 1rem; }
+.card h4 { font-size: .95rem; color: var(--color-muted); margin-bottom: .75rem; }
+
+/* ── Forms ── */
+.form-page { padding: 3rem 0; display: flex; justify-content: center; }
+.form-card { width: 100%; max-width: 440px; }
+.form-card h2 { margin-bottom: 1.5rem; text-align: center; }
+.form-group { margin-bottom: 1rem; }
+.form-group label { display: block; margin-bottom: .3rem; font-size: .875rem; color: var(--color-muted); }
+.form-group input {
+ width: 100%;
+ padding: .55rem .75rem;
+ background: var(--color-bg);
+ border: 1px solid var(--color-border);
+ border-radius: calc(var(--radius) - 2px);
+ color: var(--color-text);
+ font-size: .95rem;
+}
+.form-group input:focus { outline: 2px solid var(--color-primary); border-color: transparent; }
+.form-footer { text-align: center; margin-top: 1rem; color: var(--color-muted); font-size: .875rem; }
+
+/* ── Alerts ── */
+.alert {
+ padding: .65rem 1rem;
+ border-radius: var(--radius);
+ font-size: .875rem;
+ margin-bottom: .75rem;
+}
+.alert-error { background: #2d1a1a; color: var(--color-error); border: 1px solid #6b1d1d; }
+.alert-success { background: #0f2d1a; color: var(--color-success); border: 1px solid #1a6b3a; }
+.hidden { display: none !important; }
+
+/* ── Dashboard ── */
+.dashboard { padding: 2rem 0; }
+.dashboard h2 { font-size: 1.5rem; margin-bottom: 1.5rem; }
+
+/* ── Referral Section ── */
+.referral-invite { margin-bottom: 1.25rem; }
+.referral-link-row {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: .5rem;
+ margin-top: .4rem;
+}
+.referral-link-label { color: var(--color-muted); font-size: .875rem; white-space: nowrap; }
+.referral-link-value {
+ background: var(--color-bg);
+ border: 1px solid var(--color-border);
+ border-radius: 6px;
+ padding: .3rem .65rem;
+ font-size: .85rem;
+ word-break: break-all;
+ flex: 1;
+}
+.copy-feedback { margin-top: .4rem; font-size: .8rem; color: var(--color-success); }
+
+.referral-stats { margin-bottom: 1.25rem; }
+.stats-list { list-style: none; display: flex; flex-direction: column; gap: .3rem; }
+.stats-list li { color: var(--color-muted); font-size: .9rem; }
+.stats-list li strong { color: var(--color-text); }
+
+.referral-rewards { margin-bottom: 1rem; }
+.reward-badge {
+ display: inline-flex;
+ align-items: center;
+ gap: .4rem;
+ background: #1e1a3a;
+ border: 1px solid var(--color-primary);
+ border-radius: 6px;
+ padding: .4rem .8rem;
+ font-size: .875rem;
+ color: var(--color-primary);
+ margin: .25rem .25rem 0 0;
+}
+.reward-badge.claimed { opacity: .45; border-color: var(--color-border); color: var(--color-muted); }
+
+details { margin-top: .75rem; }
+details summary { cursor: pointer; color: var(--color-primary); font-size: .875rem; }
+#rewards-history { margin-top: .5rem; }
+
+.referral-cta { margin-top: 1rem; }
+
+/* ── Referral info page ── */
+.referral-info-page { padding: 2.5rem 0; }
+.referral-info-page h2 { font-size: 1.75rem; margin-bottom: .75rem; }
+.lead { color: var(--color-muted); font-size: 1rem; margin-bottom: 1.5rem; }
+.steps { padding-left: 1.25rem; display: flex; flex-direction: column; gap: .75rem; }
+.steps li { font-size: .95rem; }
+.conditions-list { padding-left: 1.25rem; display: flex; flex-direction: column; gap: .5rem; }
+.conditions-list li { font-size: .9rem; color: var(--color-muted); }
+.legal-note { margin-top: 1rem; font-size: .8rem; color: var(--color-muted); font-style: italic; }
+.cta-row { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 1.5rem; }
+
+/* ── Muted text ── */
+.muted { color: var(--color-muted); font-size: .875rem; }
+
+/* ── Divider ── */
+hr { border: none; border-top: 1px solid var(--color-border); margin: 1.25rem 0; }
diff --git a/public/dashboard.html b/public/dashboard.html
new file mode 100644
index 00000000..00edc8b3
--- /dev/null
+++ b/public/dashboard.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+ Evodron — Mon espace
+
+
+
+
+
+
+ Mon espace
+
+
+
+ 🎁 Programme Evodron
+
+
+
+
👤 Invitez un ami
+
+ 🔗 Votre lien de parrainage :
+ Chargement…
+
+ 📋 Copier le lien
+
+
+
✅ Lien copié !
+
+
+
+
+
+
+
📊 Statistiques
+
+ Invitations envoyées : —
+ Inscriptions : —
+ Utilisateurs ayant commencé à utiliser Evodron : —
+ Récompenses obtenues : —
+
+
+
+
+
+
+
+
🎁 Récompenses
+
+
Chargement des récompenses…
+
+
+ Voir l'historique complet
+ Chargement…
+
+
+
+
+
+
+
+
+ 🚀 Simuler une première utilisation
+
+ En situation réelle, cette action est déclenchée automatiquement après votre première
+ utilisation active d'Evodron. Elle active votre parrainage et débloque les récompenses.
+
+ Activer mon compte
+
+
+
+
+
+
+
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 00000000..e2546332
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+ Evodron — Bienvenue
+
+
+
+
+
+
+
+ Bienvenue sur Evodron
+ Invitez vos amis, collectez des récompenses, et grandissez ensemble.
+ Créer un compte
+ Découvrir le programme de parrainage
+
+
+
+
+
+
diff --git a/public/js/referral.js b/public/js/referral.js
new file mode 100644
index 00000000..fe52554e
--- /dev/null
+++ b/public/js/referral.js
@@ -0,0 +1,117 @@
+/* public/js/referral.js — Dashboard logic */
+'use strict';
+
+const TOKEN_KEY = 'evodron_token';
+
+function getToken() {
+ return localStorage.getItem(TOKEN_KEY);
+}
+
+function authHeaders() {
+ return { 'Content-Type': 'application/json', Authorization: 'Bearer ' + getToken() };
+}
+
+async function apiFetch(path, opts = {}) {
+ const res = await fetch(path, { headers: authHeaders(), ...opts });
+ if (res.status === 401) {
+ localStorage.removeItem(TOKEN_KEY);
+ location.href = '/login.html';
+ return null;
+ }
+ return res.json();
+}
+
+function renderRewardBadge(r) {
+ const label = `${r.amount} ${r.reward_type.replace(/_/g, ' ')}`;
+ const cls = r.status !== 'available' ? 'reward-badge claimed' : 'reward-badge';
+ const claim = r.status === 'available'
+ ? `Utiliser `
+ : `(${r.status}) `;
+ return `🎁 ${label} — ${r.reason.replace(/_/g, ' ')} ${claim} `;
+}
+
+async function claimReward(rewardId) {
+ const data = await apiFetch(`/api/referral/claim-reward/${rewardId}`, { method: 'POST' });
+ if (data) loadRewards();
+}
+
+async function loadReferralLink() {
+ const data = await apiFetch('/api/referral/link');
+ if (!data) return;
+ document.getElementById('referral-link-display').textContent = data.referral_link;
+
+ document.getElementById('copy-btn').addEventListener('click', () => {
+ navigator.clipboard.writeText(data.referral_link).then(() => {
+ const fb = document.getElementById('copy-feedback');
+ fb.classList.remove('hidden');
+ setTimeout(() => fb.classList.add('hidden'), 2000);
+ });
+ });
+}
+
+async function loadStats() {
+ const data = await apiFetch('/api/referral/stats');
+ if (!data) return;
+ document.getElementById('stat-invitations').textContent = data.total_invitations;
+ document.getElementById('stat-signups').textContent = data.total_signups;
+ document.getElementById('stat-active').textContent = data.total_active;
+ document.getElementById('stat-rewarded').textContent = data.total_rewarded;
+}
+
+async function loadRewards() {
+ const data = await apiFetch('/api/referral/rewards');
+ if (!data) return;
+
+ const availEl = document.getElementById('rewards-available');
+ const historyEl = document.getElementById('rewards-history');
+
+ if (data.available.length === 0) {
+ availEl.innerHTML = 'Aucune récompense disponible pour l\'instant.
';
+ } else {
+ availEl.innerHTML = data.available.map(renderRewardBadge).join('');
+ }
+
+ if (data.history.length === 0) {
+ historyEl.innerHTML = 'Aucun historique.
';
+ } else {
+ historyEl.innerHTML = data.history.map(renderRewardBadge).join('');
+ }
+}
+
+async function activateUse() {
+ const msgEl = document.getElementById('activate-msg');
+ const data = await apiFetch('/api/referral/activate-use', { method: 'POST' });
+ if (!data) return;
+ msgEl.classList.remove('hidden', 'alert-error', 'alert-success');
+ if (data.already_active) {
+ msgEl.textContent = 'Votre compte est déjà actif.';
+ msgEl.classList.add('alert-success');
+ } else if (data.activated) {
+ msgEl.textContent = '✅ Compte activé ! Les récompenses ont été créditées si vous avez un parrain.';
+ msgEl.classList.add('alert-success');
+ loadStats();
+ loadRewards();
+ } else {
+ msgEl.textContent = 'Une erreur est survenue.';
+ msgEl.classList.add('alert-error');
+ }
+}
+
+// ── Init ──────────────────────────────────────────────────────────────────
+(function init() {
+ if (!getToken()) {
+ location.href = '/login.html';
+ return;
+ }
+
+ document.getElementById('nav-logout').addEventListener('click', () => {
+ localStorage.removeItem(TOKEN_KEY);
+ location.href = '/';
+ });
+
+ document.getElementById('activate-btn').addEventListener('click', activateUse);
+
+ loadReferralLink();
+ loadStats();
+ loadRewards();
+})();
diff --git a/public/login.html b/public/login.html
new file mode 100644
index 00000000..21c3c8ab
--- /dev/null
+++ b/public/login.html
@@ -0,0 +1,66 @@
+
+
+
+
+
+ Evodron — Connexion
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/referral.html b/public/referral.html
new file mode 100644
index 00000000..b393e51c
--- /dev/null
+++ b/public/referral.html
@@ -0,0 +1,96 @@
+
+
+
+
+
+ Evodron — Programme de Parrainage
+
+
+
+
+
+
+ Programme de Parrainage Evodron
+
+ Invitez vos amis à rejoindre Evodron et recevez des récompenses lorsqu'ils commencent à utiliser la plateforme.
+
+
+
+
+ 🔄 Comment ça fonctionne ?
+
+
+ Partagez votre lien unique
+ Connectez-vous à votre espace et copiez votre lien de parrainage personnel.
+
+
+ Votre ami s'inscrit via votre lien
+ Il reçoit automatiquement un avantage de bienvenue sur son compte Evodron.
+
+
+ Il commence à utiliser Evodron
+ Dès sa première utilisation active, vous recevez votre récompense de parrain.
+
+
+
+
+
+
+ 🎁 Récompenses
+ Chargement des conditions…
+
+
+
+
+ 📋 Conditions du programme
+
+
+ Les récompenses Evodron sont des avantages au sein de la plateforme. Elles ne constituent pas
+ de l'argent réel et ne peuvent pas être échangées contre de la monnaie. Evodron se réserve le
+ droit de modifier ou d'interrompre le programme à tout moment, conformément aux conditions
+ générales d'utilisation.
+
+
+
+
+
+
+
+
+
diff --git a/public/register.html b/public/register.html
new file mode 100644
index 00000000..7ecfc4bc
--- /dev/null
+++ b/public/register.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+ Evodron — Inscription
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/config/rewards.js b/src/config/rewards.js
new file mode 100644
index 00000000..d62472de
--- /dev/null
+++ b/src/config/rewards.js
@@ -0,0 +1,58 @@
+'use strict';
+
+/**
+ * Evodron Referral Program — Rewards Configuration
+ *
+ * All reward values and conditions are defined here so that they can be
+ * changed without touching business-logic code.
+ *
+ * IMPORTANT: No financial reward is issued automatically. The reward_type
+ * must be explicitly set to a non-financial type. A future operator may
+ * add a 'financial' type only after ensuring compliance with applicable
+ * laws and platform policies.
+ */
+
+const REWARD_TYPES = {
+ CREDIT_EVODRON: 'credit_evodron',
+ FEATURE_UNLOCK: 'feature_unlock',
+ DISCOUNT: 'discount',
+ SUBSCRIPTION: 'subscription',
+ CUSTOM: 'custom',
+};
+
+/**
+ * Reward granted to the new user (referee) upon completing registration
+ * via a referral link.
+ */
+const WELCOME_BONUS = {
+ enabled: true,
+ reward_type: REWARD_TYPES.CREDIT_EVODRON,
+ amount: 10, // 10 Evodron credits
+ reason: 'welcome_bonus',
+};
+
+/**
+ * Reward granted to the referrer once the referee reaches the activation
+ * condition defined in ACTIVATION_CONDITION below.
+ */
+const REFERRER_REWARD = {
+ enabled: true,
+ reward_type: REWARD_TYPES.CREDIT_EVODRON,
+ amount: 20, // 20 Evodron credits
+ reason: 'referral_activation',
+};
+
+/**
+ * Condition that must be met by the referee before the referrer reward
+ * is unlocked. Supported values:
+ * 'first_use' — referee must call POST /api/referral/activate-use once
+ * (triggered by the application after a meaningful action)
+ */
+const ACTIVATION_CONDITION = 'first_use';
+
+module.exports = {
+ REWARD_TYPES,
+ WELCOME_BONUS,
+ REFERRER_REWARD,
+ ACTIVATION_CONDITION,
+};
diff --git a/src/db/database.js b/src/db/database.js
new file mode 100644
index 00000000..5a34fd1a
--- /dev/null
+++ b/src/db/database.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const path = require('path');
+const fs = require('fs');
+const Database = require('better-sqlite3');
+
+const DB_PATH = process.env.DB_PATH || path.join(__dirname, '../../evodron.db');
+const SCHEMA = path.join(__dirname, 'schema.sql');
+
+let db;
+
+function getDb() {
+ if (!db) {
+ db = new Database(DB_PATH);
+ db.pragma('journal_mode = WAL');
+ db.pragma('foreign_keys = ON');
+ const schema = fs.readFileSync(SCHEMA, 'utf8');
+ db.exec(schema);
+ }
+ return db;
+}
+
+function closeDb() {
+ if (db) {
+ db.close();
+ db = null;
+ }
+}
+
+module.exports = { getDb, closeDb };
diff --git a/src/db/schema.sql b/src/db/schema.sql
new file mode 100644
index 00000000..79cd79d0
--- /dev/null
+++ b/src/db/schema.sql
@@ -0,0 +1,59 @@
+-- Evodron Referral Program — Database Schema
+
+PRAGMA foreign_keys = ON;
+
+-- Users table
+CREATE TABLE IF NOT EXISTS users (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ email TEXT NOT NULL UNIQUE,
+ username TEXT NOT NULL,
+ password_hash TEXT NOT NULL,
+ referral_code TEXT NOT NULL UNIQUE,
+ referred_by_user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
+ is_active INTEGER NOT NULL DEFAULT 0, -- 1 once the user has completed first meaningful use
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
+);
+
+-- Referrals table
+-- One row per referrer/referee pair; referee_id is UNIQUE (one referrer per user)
+CREATE TABLE IF NOT EXISTS referrals (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ referrer_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+ referee_id INTEGER NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,
+ status TEXT NOT NULL DEFAULT 'pending'
+ CHECK(status IN ('pending', 'active', 'rewarded')),
+ referral_depth INTEGER NOT NULL DEFAULT 1, -- reserved for multi-level support
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
+ activated_at TEXT
+);
+
+-- Rewards table
+CREATE TABLE IF NOT EXISTS rewards (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+ reward_type TEXT NOT NULL
+ CHECK(reward_type IN ('credit_evodron', 'feature_unlock', 'discount', 'subscription', 'custom')),
+ amount REAL NOT NULL DEFAULT 0,
+ reason TEXT NOT NULL
+ CHECK(reason IN ('referral_activation', 'welcome_bonus', 'custom')),
+ status TEXT NOT NULL DEFAULT 'available'
+ CHECK(status IN ('available', 'claimed', 'expired')),
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
+ claimed_at TEXT
+);
+
+-- Referral events log (audit trail, extensible)
+CREATE TABLE IF NOT EXISTS referral_events (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ referral_id INTEGER NOT NULL REFERENCES referrals(id) ON DELETE CASCADE,
+ event_type TEXT NOT NULL
+ CHECK(event_type IN ('signup', 'first_use', 'reward_granted', 'reward_claimed')),
+ metadata TEXT, -- JSON string for extensible payload
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
+);
+
+-- Indexes
+CREATE INDEX IF NOT EXISTS idx_users_referral_code ON users(referral_code);
+CREATE INDEX IF NOT EXISTS idx_referrals_referrer_id ON referrals(referrer_id);
+CREATE INDEX IF NOT EXISTS idx_rewards_user_id ON rewards(user_id);
+CREATE INDEX IF NOT EXISTS idx_referral_events_referral ON referral_events(referral_id);
diff --git a/src/middleware/auth.js b/src/middleware/auth.js
new file mode 100644
index 00000000..78c4a5f8
--- /dev/null
+++ b/src/middleware/auth.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const jwt = require('jsonwebtoken');
+
+const JWT_SECRET = process.env.JWT_SECRET;
+if (!JWT_SECRET) {
+ throw new Error('JWT_SECRET environment variable is required');
+}
+
+const JWT_EXPIRY = process.env.JWT_EXPIRY || '7d';
+
+function signToken(payload) {
+ return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRY });
+}
+
+function requireAuth(req, res, next) {
+ const authHeader = req.headers.authorization;
+ let token;
+
+ if (authHeader && authHeader.startsWith('Bearer ')) {
+ token = authHeader.slice(7);
+ } else if (req.cookies && req.cookies.token) {
+ token = req.cookies.token;
+ }
+
+ if (!token) {
+ return res.status(401).json({ error: 'Authentication required' });
+ }
+
+ try {
+ req.user = jwt.verify(token, JWT_SECRET);
+ next();
+ } catch {
+ return res.status(401).json({ error: 'Invalid or expired token' });
+ }
+}
+
+module.exports = { signToken, requireAuth };
diff --git a/src/models/referral.js b/src/models/referral.js
new file mode 100644
index 00000000..4dd37864
--- /dev/null
+++ b/src/models/referral.js
@@ -0,0 +1,80 @@
+'use strict';
+
+const { getDb } = require('../db/database');
+
+/**
+ * Create a referral record linking referrer → referee.
+ * Guards:
+ * - referrer_id !== referee_id (no self-referral)
+ * - referee_id UNIQUE constraint in DB prevents duplicate parrain
+ */
+function createReferral(referrerId, refereeId) {
+ if (referrerId === refereeId) {
+ throw new Error('SELF_REFERRAL');
+ }
+
+ const db = getDb();
+ const stmt = db.prepare(`
+ INSERT INTO referrals (referrer_id, referee_id, status)
+ VALUES (?, ?, 'pending')
+ `);
+
+ const result = stmt.run(referrerId, refereeId);
+ return findById(result.lastInsertRowid);
+}
+
+function findById(id) {
+ return getDb()
+ .prepare('SELECT * FROM referrals WHERE id = ?')
+ .get(id);
+}
+
+function findByRefereeId(refereeId) {
+ return getDb()
+ .prepare('SELECT * FROM referrals WHERE referee_id = ?')
+ .get(refereeId);
+}
+
+function getReferrerStats(referrerId) {
+ const db = getDb();
+ return {
+ total_invitations: db.prepare('SELECT COUNT(*) AS n FROM referrals WHERE referrer_id = ?').get(referrerId).n,
+ total_signups: db.prepare("SELECT COUNT(*) AS n FROM referrals WHERE referrer_id = ? AND status IN ('pending','active','rewarded')").get(referrerId).n,
+ total_active: db.prepare("SELECT COUNT(*) AS n FROM referrals WHERE referrer_id = ? AND status IN ('active','rewarded')").get(referrerId).n,
+ total_rewarded: db.prepare("SELECT COUNT(*) AS n FROM referrals WHERE referrer_id = ? AND status = 'rewarded'").get(referrerId).n,
+ };
+}
+
+/**
+ * Mark a referral as active (filleul has completed the activation condition).
+ * Returns the updated referral row.
+ */
+function activateReferral(referralId) {
+ getDb()
+ .prepare("UPDATE referrals SET status = 'active', activated_at = datetime('now') WHERE id = ? AND status = 'pending'")
+ .run(referralId);
+ return findById(referralId);
+}
+
+function markRewarded(referralId) {
+ getDb()
+ .prepare("UPDATE referrals SET status = 'rewarded' WHERE id = ?")
+ .run(referralId);
+ return findById(referralId);
+}
+
+function logEvent(referralId, eventType, metadata = null) {
+ getDb()
+ .prepare('INSERT INTO referral_events (referral_id, event_type, metadata) VALUES (?, ?, ?)')
+ .run(referralId, eventType, metadata ? JSON.stringify(metadata) : null);
+}
+
+module.exports = {
+ createReferral,
+ findById,
+ findByRefereeId,
+ getReferrerStats,
+ activateReferral,
+ markRewarded,
+ logEvent,
+};
diff --git a/src/models/reward.js b/src/models/reward.js
new file mode 100644
index 00000000..22562804
--- /dev/null
+++ b/src/models/reward.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const { getDb } = require('../db/database');
+const { WELCOME_BONUS, REFERRER_REWARD } = require('../config/rewards');
+
+function grantWelcomeBonus(userId) {
+ if (!WELCOME_BONUS.enabled) return null;
+ return _createReward({
+ user_id: userId,
+ reward_type: WELCOME_BONUS.reward_type,
+ amount: WELCOME_BONUS.amount,
+ reason: WELCOME_BONUS.reason,
+ });
+}
+
+function grantReferrerReward(referrerId) {
+ if (!REFERRER_REWARD.enabled) return null;
+ return _createReward({
+ user_id: referrerId,
+ reward_type: REFERRER_REWARD.reward_type,
+ amount: REFERRER_REWARD.amount,
+ reason: REFERRER_REWARD.reason,
+ });
+}
+
+function _createReward({ user_id, reward_type, amount, reason }) {
+ const db = getDb();
+ const result = db.prepare(`
+ INSERT INTO rewards (user_id, reward_type, amount, reason)
+ VALUES (?, ?, ?, ?)
+ `).run(user_id, reward_type, amount, reason);
+
+ return db.prepare('SELECT * FROM rewards WHERE id = ?').get(result.lastInsertRowid);
+}
+
+function getRewardsForUser(userId) {
+ return getDb()
+ .prepare("SELECT * FROM rewards WHERE user_id = ? ORDER BY created_at DESC")
+ .all(userId);
+}
+
+function getAvailableRewards(userId) {
+ return getDb()
+ .prepare("SELECT * FROM rewards WHERE user_id = ? AND status = 'available' ORDER BY created_at DESC")
+ .all(userId);
+}
+
+function claimReward(rewardId, userId) {
+ const db = getDb();
+ const reward = db.prepare('SELECT * FROM rewards WHERE id = ? AND user_id = ?').get(rewardId, userId);
+ if (!reward) throw new Error('REWARD_NOT_FOUND');
+ if (reward.status !== 'available') throw new Error('REWARD_NOT_AVAILABLE');
+
+ db.prepare("UPDATE rewards SET status = 'claimed', claimed_at = datetime('now') WHERE id = ?").run(rewardId);
+ return db.prepare('SELECT * FROM rewards WHERE id = ?').get(rewardId);
+}
+
+module.exports = { grantWelcomeBonus, grantReferrerReward, getRewardsForUser, getAvailableRewards, claimReward };
diff --git a/src/models/user.js b/src/models/user.js
new file mode 100644
index 00000000..21c81f64
--- /dev/null
+++ b/src/models/user.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const { customAlphabet } = require('nanoid');
+const { getDb } = require('../db/database');
+
+// 8-character alphanumeric referral codes (upper-case only for readability)
+const generateCode = customAlphabet('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', 8);
+
+function createUser({ email, username, password_hash, referred_by_user_id = null }) {
+ const db = getDb();
+ const code = generateCode();
+
+ const stmt = db.prepare(`
+ INSERT INTO users (email, username, password_hash, referral_code, referred_by_user_id)
+ VALUES (?, ?, ?, ?, ?)
+ `);
+
+ const result = stmt.run(
+ email.toLowerCase().trim(),
+ username.trim(),
+ password_hash,
+ code,
+ referred_by_user_id
+ );
+
+ return findById(result.lastInsertRowid);
+}
+
+function findById(id) {
+ return getDb()
+ .prepare('SELECT id, email, username, referral_code, referred_by_user_id, is_active, created_at FROM users WHERE id = ?')
+ .get(id);
+}
+
+function findByEmail(email) {
+ return getDb()
+ .prepare('SELECT * FROM users WHERE email = ?')
+ .get(email.toLowerCase().trim());
+}
+
+function findByReferralCode(code) {
+ return getDb()
+ .prepare('SELECT id, email, username, referral_code FROM users WHERE referral_code = ?')
+ .get(code);
+}
+
+function markActive(userId) {
+ return getDb()
+ .prepare('UPDATE users SET is_active = 1 WHERE id = ?')
+ .run(userId);
+}
+
+module.exports = { createUser, findById, findByEmail, findByReferralCode, markActive, generateCode };
diff --git a/src/routes/auth.js b/src/routes/auth.js
new file mode 100644
index 00000000..39d5d967
--- /dev/null
+++ b/src/routes/auth.js
@@ -0,0 +1,93 @@
+'use strict';
+
+const express = require('express');
+const bcrypt = require('bcryptjs');
+const UserModel = require('../models/user');
+const ReferralModel = require('../models/referral');
+const RewardModel = require('../models/reward');
+const { signToken } = require('../middleware/auth');
+
+const router = express.Router();
+
+/**
+ * POST /api/auth/register
+ * Body: { email, username, password, referral_code? }
+ */
+router.post('/register', async (req, res) => {
+ try {
+ const { email, username, password, referral_code } = req.body;
+
+ if (!email || !username || !password) {
+ return res.status(400).json({ error: 'email, username and password are required' });
+ }
+ if (password.length < 8) {
+ return res.status(400).json({ error: 'Password must be at least 8 characters' });
+ }
+
+ // Check for duplicate email
+ if (UserModel.findByEmail(email)) {
+ return res.status(409).json({ error: 'Email already registered' });
+ }
+
+ // Resolve referrer (silent ignore if code is invalid)
+ let referrer = null;
+ if (referral_code) {
+ referrer = UserModel.findByReferralCode(referral_code);
+ }
+
+ const password_hash = await bcrypt.hash(password, 12);
+ const newUser = UserModel.createUser({
+ email,
+ username,
+ password_hash,
+ referred_by_user_id: referrer ? referrer.id : null,
+ });
+
+ // Create referral record and grant welcome bonus
+ if (referrer && referrer.id !== newUser.id) {
+ try {
+ const referral = ReferralModel.createReferral(referrer.id, newUser.id);
+ ReferralModel.logEvent(referral.id, 'signup');
+ RewardModel.grantWelcomeBonus(newUser.id);
+ } catch (e) {
+ // SELF_REFERRAL or DB unique violation — silently skip
+ }
+ }
+
+ const token = signToken({ id: newUser.id, email: newUser.email });
+ return res.status(201).json({ token, user: newUser });
+ } catch (err) {
+ return res.status(500).json({ error: 'Internal server error' });
+ }
+});
+
+/**
+ * POST /api/auth/login
+ * Body: { email, password }
+ */
+router.post('/login', async (req, res) => {
+ try {
+ const { email, password } = req.body;
+ if (!email || !password) {
+ return res.status(400).json({ error: 'email and password are required' });
+ }
+
+ const user = UserModel.findByEmail(email);
+ if (!user) {
+ return res.status(401).json({ error: 'Invalid credentials' });
+ }
+
+ const valid = await bcrypt.compare(password, user.password_hash);
+ if (!valid) {
+ return res.status(401).json({ error: 'Invalid credentials' });
+ }
+
+ const token = signToken({ id: user.id, email: user.email });
+ const safeUser = UserModel.findById(user.id);
+ return res.json({ token, user: safeUser });
+ } catch {
+ return res.status(500).json({ error: 'Internal server error' });
+ }
+});
+
+module.exports = router;
diff --git a/src/routes/referral.js b/src/routes/referral.js
new file mode 100644
index 00000000..d955b7b0
--- /dev/null
+++ b/src/routes/referral.js
@@ -0,0 +1,119 @@
+'use strict';
+
+const express = require('express');
+const UserModel = require('../models/user');
+const ReferralModel = require('../models/referral');
+const RewardModel = require('../models/reward');
+const { requireAuth } = require('../middleware/auth');
+const { ACTIVATION_CONDITION, REFERRER_REWARD, WELCOME_BONUS, REWARD_TYPES } = require('../config/rewards');
+
+const router = express.Router();
+
+/**
+ * GET /api/referral/link
+ * Returns the authenticated user's referral link and code.
+ */
+router.get('/link', requireAuth, (req, res) => {
+ const user = UserModel.findById(req.user.id);
+ if (!user) return res.status(404).json({ error: 'User not found' });
+
+ const base = process.env.APP_URL || `${req.protocol}://${req.get('host')}`;
+ const link = `${base}/register?ref=${user.referral_code}`;
+
+ return res.json({ referral_code: user.referral_code, referral_link: link });
+});
+
+/**
+ * GET /api/referral/stats
+ * Returns referral statistics for the authenticated user.
+ */
+router.get('/stats', requireAuth, (req, res) => {
+ const stats = ReferralModel.getReferrerStats(req.user.id);
+ return res.json(stats);
+});
+
+/**
+ * GET /api/referral/rewards
+ * Returns all rewards for the authenticated user.
+ */
+router.get('/rewards', requireAuth, (req, res) => {
+ const all = RewardModel.getRewardsForUser(req.user.id);
+ const available = RewardModel.getAvailableRewards(req.user.id);
+ return res.json({ available, history: all });
+});
+
+/**
+ * POST /api/referral/claim-reward/:rewardId
+ * Claim an available reward.
+ */
+router.post('/claim-reward/:rewardId', requireAuth, (req, res) => {
+ try {
+ const reward = RewardModel.claimReward(Number(req.params.rewardId), req.user.id);
+ return res.json({ reward });
+ } catch (e) {
+ if (e.message === 'REWARD_NOT_FOUND') return res.status(404).json({ error: 'Reward not found' });
+ if (e.message === 'REWARD_NOT_AVAILABLE') return res.status(409).json({ error: 'Reward already claimed or expired' });
+ return res.status(500).json({ error: 'Internal server error' });
+ }
+});
+
+/**
+ * POST /api/referral/activate-use
+ * Called by the application when the authenticated user completes their
+ * first meaningful action. Triggers the referrer reward if applicable.
+ *
+ * This endpoint is idempotent: calling it multiple times has no effect
+ * once the user is already active.
+ */
+router.post('/activate-use', requireAuth, (req, res) => {
+ const user = UserModel.findById(req.user.id);
+ if (!user) return res.status(404).json({ error: 'User not found' });
+
+ // Already active — nothing to do
+ if (user.is_active) {
+ return res.json({ already_active: true });
+ }
+
+ UserModel.markActive(user.id);
+
+ // Check if this user was referred
+ const referral = ReferralModel.findByRefereeId(user.id);
+ if (referral && referral.status === 'pending') {
+ ReferralModel.activateReferral(referral.id);
+ ReferralModel.logEvent(referral.id, 'first_use');
+
+ // Grant referrer reward
+ const reward = RewardModel.grantReferrerReward(referral.referrer_id);
+ if (reward) {
+ ReferralModel.logEvent(referral.id, 'reward_granted', { reward_id: reward.id });
+ ReferralModel.markRewarded(referral.id);
+ }
+ }
+
+ return res.json({ activated: true });
+});
+
+/**
+ * GET /api/referral/program-info
+ * Returns the current program conditions (public, no auth required).
+ */
+router.get('/program-info', (req, res) => {
+ return res.json({
+ welcome_bonus: WELCOME_BONUS.enabled
+ ? { type: WELCOME_BONUS.reward_type, amount: WELCOME_BONUS.amount }
+ : null,
+ referrer_reward: REFERRER_REWARD.enabled
+ ? { type: REFERRER_REWARD.reward_type, amount: REFERRER_REWARD.amount }
+ : null,
+ activation_condition: ACTIVATION_CONDITION,
+ reward_types: Object.values(REWARD_TYPES),
+ conditions: [
+ 'Un utilisateur ne peut parrainer qu\'un ami qu\'une seule fois.',
+ 'L\'auto-parrainage est interdit.',
+ 'La récompense du parrain est créditée uniquement après la première utilisation active du filleul.',
+ 'Les récompenses ne sont pas de l\'argent réel et sont soumises aux conditions générales Evodron.',
+ ],
+ });
+});
+
+module.exports = router;
diff --git a/tests/anti-abuse.test.js b/tests/anti-abuse.test.js
new file mode 100644
index 00000000..bcff59a4
--- /dev/null
+++ b/tests/anti-abuse.test.js
@@ -0,0 +1,137 @@
+'use strict';
+
+/**
+ * Tests for Evodron Referral Program — anti-abuse protections.
+ */
+
+process.env.JWT_SECRET = 'test-secret-do-not-use-in-production';
+process.env.DB_PATH = ':memory:';
+
+const request = require('supertest');
+const app = require('../app');
+
+function bearer(token) {
+ return 'Bearer ' + token;
+}
+
+async function register(agent, overrides) {
+ const opts = overrides || {};
+ return agent.post('/api/auth/register').send({
+ email: opts.email || ('user_' + Date.now() + '_' + Math.random() + '@test.com'),
+ username: opts.username || 'TestUser',
+ password: opts.password || 'Password123',
+ referral_code: opts.referral_code,
+ });
+}
+
+async function login(agent, email) {
+ const res = await agent.post('/api/auth/login').send({ email, password: 'Password123' });
+ return res.body.token;
+}
+
+// ── Self-referral ─────────────────────────────────────────────────────────
+
+describe('Anti-abuse: self-referral', () => {
+ const agent = request(app);
+
+ test('user cannot use their own referral code (same email → 409 first)', async () => {
+ const email = 'self_' + Date.now() + '@test.com';
+ const firstRes = await register(agent, { email });
+ const myCode = firstRes.body.user.referral_code;
+
+ const res2 = await register(agent, { email, referral_code: myCode });
+ expect(res2.status).toBe(409);
+ });
+
+ test('model-level self-referral guard throws SELF_REFERRAL', () => {
+ const ReferralModel = require('../src/models/referral');
+ expect(() => ReferralModel.createReferral(5, 5)).toThrow('SELF_REFERRAL');
+ });
+});
+
+// ── Duplicate parrain ─────────────────────────────────────────────────────
+
+describe('Anti-abuse: duplicate parrain', () => {
+ const agent = request(app);
+
+ test('a user can only have one referral (DB UNIQUE constraint)', async () => {
+ const ref1Email = 'ref1_' + Date.now() + '@test.com';
+ const ref2Email = 'ref2_' + Date.now() + '@test.com';
+ const ref1Res = await register(agent, { email: ref1Email });
+ const ref2Res = await register(agent, { email: ref2Email });
+ const code1 = ref1Res.body.user.referral_code;
+
+ const newEmail = 'newbie_' + Date.now() + '@test.com';
+ await register(agent, { email: newEmail, referral_code: code1 });
+
+ const UserModel = require('../src/models/user');
+ const ReferralModel = require('../src/models/referral');
+
+ const referee = UserModel.findByEmail(newEmail);
+ const ref2User = UserModel.findByEmail(ref2Email);
+
+ expect(() => ReferralModel.createReferral(ref2User.id, referee.id)).toThrow();
+ });
+});
+
+// ── Invalid code ──────────────────────────────────────────────────────────
+
+describe('Anti-abuse: invalid referral code', () => {
+ const agent = request(app);
+
+ test('registration with invalid referral code succeeds silently', async () => {
+ const res = await register(agent, {
+ email: 'invalid_ref_' + Date.now() + '@test.com',
+ referral_code: 'XXXXXXXX',
+ });
+ expect(res.status).toBe(201);
+ expect(res.body.user.referred_by_user_id).toBeNull();
+ });
+});
+
+// ── Reward timing ─────────────────────────────────────────────────────────
+
+describe('Anti-abuse: reward not granted without activation', () => {
+ const agent = request(app);
+
+ test('referrer receives NO referral_activation reward at referee signup', async () => {
+ const refEmail = 'noreward_' + Date.now() + '@test.com';
+ const refRes = await register(agent, { email: refEmail });
+ const refCode = refRes.body.user.referral_code;
+ const refToken = await login(agent, refEmail);
+
+ await register(agent, { email: 'newreferee_' + Date.now() + '@test.com', referral_code: refCode });
+
+ const rwRes = await agent.get('/api/referral/rewards').set('Authorization', bearer(refToken));
+ const activationRewards = rwRes.body.available.filter(r => r.reason === 'referral_activation');
+ expect(activationRewards.length).toBe(0);
+ });
+});
+
+// ── Claim isolation ───────────────────────────────────────────────────────
+
+describe('Anti-abuse: claim reward isolation', () => {
+ const agent = request(app);
+
+ test('cannot claim another user\'s reward', async () => {
+ const refEmail = 'claimref_' + Date.now() + '@test.com';
+ const refRes = await register(agent, { email: refEmail });
+ const refCode = refRes.body.user.referral_code;
+
+ const email1 = 'claim1_' + Date.now() + '@test.com';
+ const email2 = 'claim2_' + Date.now() + '@test.com';
+ await register(agent, { email: email1, referral_code: refCode });
+ await register(agent, { email: email2 });
+
+ const token1 = await login(agent, email1);
+ const token2 = await login(agent, email2);
+
+ const rwRes = await agent.get('/api/referral/rewards').set('Authorization', bearer(token1));
+ const reward = rwRes.body.available[0];
+ if (!reward) return;
+
+ const claimRes = await agent.post('/api/referral/claim-reward/' + reward.id)
+ .set('Authorization', bearer(token2));
+ expect(claimRes.status).toBe(404);
+ });
+});
diff --git a/tests/referral.test.js b/tests/referral.test.js
new file mode 100644
index 00000000..2498a463
--- /dev/null
+++ b/tests/referral.test.js
@@ -0,0 +1,196 @@
+'use strict';
+
+/**
+ * Tests for the Evodron Referral Program core functionality.
+ * Uses supertest against the Express app with an in-memory SQLite DB.
+ */
+
+process.env.JWT_SECRET = 'test-secret-do-not-use-in-production';
+process.env.DB_PATH = ':memory:';
+
+const request = require('supertest');
+const app = require('../app');
+
+// ── Helpers ──────────────────────────────────────────────────────────────
+
+function bearer(token) {
+ return 'Bearer ' + token;
+}
+
+async function register(agent, overrides = {}) {
+ const body = {
+ email: overrides.email || ('user_' + Date.now() + '_' + Math.random() + '@test.com'),
+ username: overrides.username || 'TestUser',
+ password: overrides.password || 'Password123',
+ ...overrides,
+ };
+ return agent.post('/api/auth/register').send(body);
+}
+
+async function login(agent, email, password) {
+ const res = await agent.post('/api/auth/login').send({ email, password: password || 'Password123' });
+ return res.body.token;
+}
+
+// ── Auth Routes ───────────────────────────────────────────────────────────
+
+describe('POST /api/auth/register', () => {
+ const agent = request(app);
+
+ test('registers a new user successfully', async () => {
+ const res = await register(agent);
+ expect(res.status).toBe(201);
+ expect(res.body).toHaveProperty('token');
+ expect(res.body.user).toHaveProperty('referral_code');
+ expect(res.body.user.referral_code).toHaveLength(8);
+ });
+
+ test('rejects duplicate email', async () => {
+ const email = 'dup_' + Date.now() + '@test.com';
+ await register(agent, { email });
+ const res2 = await register(agent, { email });
+ expect(res2.status).toBe(409);
+ });
+
+ test('rejects short password', async () => {
+ const res = await register(agent, { password: 'short' });
+ expect(res.status).toBe(400);
+ });
+
+ test('rejects missing fields', async () => {
+ const res = await agent.post('/api/auth/register').send({ email: 'x@y.com' });
+ expect(res.status).toBe(400);
+ });
+});
+
+describe('POST /api/auth/login', () => {
+ const agent = request(app);
+
+ test('logs in with correct credentials', async () => {
+ const email = 'login_' + Date.now() + '@test.com';
+ await register(agent, { email });
+ const token = await login(agent, email);
+ expect(typeof token).toBe('string');
+ expect(token.length).toBeGreaterThan(10);
+ });
+
+ test('rejects wrong password', async () => {
+ const email = 'wrongpw_' + Date.now() + '@test.com';
+ await register(agent, { email });
+ const res = await agent.post('/api/auth/login').send({ email, password: 'WrongPass1' });
+ expect(res.status).toBe(401);
+ });
+});
+
+// ── Referral Link ─────────────────────────────────────────────────────────
+
+describe('GET /api/referral/link', () => {
+ const agent = request(app);
+
+ test('returns referral link for authenticated user', async () => {
+ const email = 'link_' + Date.now() + '@test.com';
+ await register(agent, { email });
+ const token = await login(agent, email);
+ const res = await agent.get('/api/referral/link').set('Authorization', bearer(token));
+ expect(res.status).toBe(200);
+ expect(res.body).toHaveProperty('referral_link');
+ expect(res.body.referral_link).toContain('ref=');
+ });
+
+ test('returns 401 without token', async () => {
+ const res = await agent.get('/api/referral/link');
+ expect(res.status).toBe(401);
+ });
+});
+
+// ── Stats ─────────────────────────────────────────────────────────────────
+
+describe('GET /api/referral/stats', () => {
+ const agent = request(app);
+
+ test('returns zero stats for new user', async () => {
+ const email = 'stats_' + Date.now() + '@test.com';
+ await register(agent, { email });
+ const token = await login(agent, email);
+ const res = await agent.get('/api/referral/stats').set('Authorization', bearer(token));
+ expect(res.status).toBe(200);
+ expect(res.body.total_invitations).toBe(0);
+ expect(res.body.total_signups).toBe(0);
+ });
+});
+
+// ── Referral flow ─────────────────────────────────────────────────────────
+
+describe('Referral flow', () => {
+ const agent = request(app);
+
+ test('referee gets welcome bonus when registering with valid referral code', async () => {
+ const refEmail = 'referrer_' + Date.now() + '@test.com';
+ const refRes = await register(agent, { email: refEmail });
+ const refCode = refRes.body.user.referral_code;
+
+ const newEmail = 'referee_' + Date.now() + '@test.com';
+ await register(agent, { email: newEmail, referral_code: refCode });
+ const newToken = await login(agent, newEmail);
+
+ const rewardRes = await agent.get('/api/referral/rewards').set('Authorization', bearer(newToken));
+ expect(rewardRes.status).toBe(200);
+ expect(rewardRes.body.available.length).toBeGreaterThan(0);
+ expect(rewardRes.body.available[0].reason).toBe('welcome_bonus');
+ });
+
+ test('referrer stats increment after referee signs up', async () => {
+ const refEmail = 'referrer2_' + Date.now() + '@test.com';
+ const refRes = await register(agent, { email: refEmail });
+ const refCode = refRes.body.user.referral_code;
+ const refToken = await login(agent, refEmail);
+
+ await register(agent, { email: 'referee2_' + Date.now() + '@test.com', referral_code: refCode });
+
+ const statsRes = await agent.get('/api/referral/stats').set('Authorization', bearer(refToken));
+ expect(statsRes.body.total_signups).toBe(1);
+ });
+
+ test('referrer gets reward after referee activates', async () => {
+ const refEmail = 'referrer3_' + Date.now() + '@test.com';
+ const refRes = await register(agent, { email: refEmail });
+ const refCode = refRes.body.user.referral_code;
+ const refToken = await login(agent, refEmail);
+
+ const newEmail = 'referee3_' + Date.now() + '@test.com';
+ await register(agent, { email: newEmail, referral_code: refCode });
+ const newToken = await login(agent, newEmail);
+
+ const activRes = await agent.post('/api/referral/activate-use').set('Authorization', bearer(newToken));
+ expect(activRes.status).toBe(200);
+ expect(activRes.body.activated).toBe(true);
+
+ const rwRes = await agent.get('/api/referral/rewards').set('Authorization', bearer(refToken));
+ expect(rwRes.body.available.some(r => r.reason === 'referral_activation')).toBe(true);
+
+ const statsRes = await agent.get('/api/referral/stats').set('Authorization', bearer(refToken));
+ expect(statsRes.body.total_rewarded).toBe(1);
+ });
+
+ test('activate-use is idempotent', async () => {
+ const email = 'idem_' + Date.now() + '@test.com';
+ await register(agent, { email });
+ const token = await login(agent, email);
+
+ await agent.post('/api/referral/activate-use').set('Authorization', bearer(token));
+ const res2 = await agent.post('/api/referral/activate-use').set('Authorization', bearer(token));
+ expect(res2.status).toBe(200);
+ expect(res2.body.already_active).toBe(true);
+ });
+});
+
+// ── Program info ──────────────────────────────────────────────────────────
+
+describe('GET /api/referral/program-info', () => {
+ test('returns public program info without auth', async () => {
+ const res = await request(app).get('/api/referral/program-info');
+ expect(res.status).toBe(200);
+ expect(res.body).toHaveProperty('conditions');
+ expect(Array.isArray(res.body.conditions)).toBe(true);
+ });
+});
From e697b428847c9fd39126c2f3ba57ec87dc609271 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 17:57:51 +0000
Subject: [PATCH 02/13] =?UTF-8?q?feat:=20EVODRON=20architecture=20?=
=?UTF-8?q?=E2=80=94=20rate=20limiting,=20health=20check,=20Docker,=20CI,?=
=?UTF-8?q?=20docs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
.env.example | 29 +++++++
.github/workflows/ci.yml | 28 ++++++
CONTRIBUTING.md | 48 +++++++++++
Dockerfile | 22 +++++
EVODRON.md | 156 ++++++++++++++++++++++++++++++++++
SECURITY.md | 26 ++++++
app.js | 9 +-
docker-compose.yml | 22 +++++
package-lock.json | 52 ++++++++++++
package.json | 5 +-
src/middleware/rateLimiter.js | 31 +++++++
src/routes/health.js | 28 ++++++
tests/health.test.js | 17 ++++
13 files changed, 469 insertions(+), 4 deletions(-)
create mode 100644 .env.example
create mode 100644 .github/workflows/ci.yml
create mode 100644 CONTRIBUTING.md
create mode 100644 Dockerfile
create mode 100644 EVODRON.md
create mode 100644 SECURITY.md
create mode 100644 docker-compose.yml
create mode 100644 src/middleware/rateLimiter.js
create mode 100644 src/routes/health.js
create mode 100644 tests/health.test.js
diff --git a/.env.example b/.env.example
new file mode 100644
index 00000000..9cb74ef7
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,29 @@
+# Variables d'environnement — Evodron
+
+# Copier ce fichier en `.env` et remplir les valeurs.
+# Ne jamais committer `.env` dans le dépôt.
+
+# ── Sécurité ──────────────────────────────────────────────────────────────
+# Clé secrète JWT. Utiliser une valeur aléatoire longue (minimum 32 caractères).
+# Exemple : openssl rand -hex 32
+JWT_SECRET=changeme-use-a-long-random-value-here
+
+# Durée de validité des tokens JWT (défaut : 7d)
+# Formats acceptés : "7d", "24h", "3600s"
+JWT_EXPIRY=7d
+
+# ── Serveur ───────────────────────────────────────────────────────────────
+PORT=3000
+
+# URL publique de l'application (utilisée pour générer les liens de parrainage)
+# Exemple : https://app.evodron.com
+APP_URL=http://localhost:3000
+
+# ── Base de données ───────────────────────────────────────────────────────
+# Chemin vers le fichier SQLite (défaut : ./evodron.db)
+# Utiliser :memory: pour les tests uniquement
+DB_PATH=./evodron.db
+
+# ── Environnement ─────────────────────────────────────────────────────────
+# Valeurs : development | production | test
+NODE_ENV=development
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..e8629a5f
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,28 @@
+name: CI
+
+on:
+ push:
+ branches: ["**"]
+ pull_request:
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: npm
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run tests
+ env:
+ JWT_SECRET: test-secret-ci
+ DB_PATH: ":memory:"
+ NODE_ENV: test
+ run: npm test
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..242ef9c6
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,48 @@
+# Guide de contribution — Evodron
+
+Merci de contribuer à Evodron ! Voici les règles à suivre.
+
+## Pré-requis
+
+- Node.js >= 18
+- npm >= 9
+
+## Installation locale
+
+```bash
+git clone https://github.com/julesdemangeot-ship-it/EVODRON.git
+cd EVODRON
+npm install
+cp .env.example .env
+# Éditer .env et définir JWT_SECRET
+```
+
+## Lancer les tests
+
+```bash
+npm test
+```
+
+Les tests utilisent une base SQLite en mémoire. Aucune configuration externe requise.
+
+## Conventions
+
+- **Code** : `'use strict'` en tête de chaque fichier JS.
+- **Commits** : messages en anglais, préfixés (`feat:`, `fix:`, `chore:`, `docs:`, `test:`).
+- **Branches** : `feature/`, `fix/`, `chore/`.
+- **Tests** : toute nouvelle fonctionnalité doit être accompagnée de tests dans `tests/`.
+
+## Structure du code EVODRON
+
+Voir `EVODRON.md` pour la description complète de l'architecture.
+
+## Pull Requests
+
+1. Créer une branche depuis `main`.
+2. Écrire ou adapter les tests.
+3. S'assurer que `npm test` passe à 100%.
+4. Ouvrir une PR avec une description claire.
+
+## Sécurité
+
+Voir `SECURITY.md` pour signaler une vulnérabilité.
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..41adc800
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,22 @@
+FROM node:20-alpine
+
+WORKDIR /app
+
+# Install dependencies first (layer cache)
+COPY package*.json ./
+RUN npm ci --omit=dev
+
+# Copy application source
+COPY app.js ./
+COPY src/ ./src/
+COPY public/ ./public/
+
+# SQLite database volume mount point
+VOLUME ["/data"]
+ENV DB_PATH=/data/evodron.db
+
+EXPOSE 3000
+
+USER node
+
+CMD ["node", "app.js"]
diff --git a/EVODRON.md b/EVODRON.md
new file mode 100644
index 00000000..c527a876
--- /dev/null
+++ b/EVODRON.md
@@ -0,0 +1,156 @@
+# Evodron
+
+**Plateforme de parrainage** — backend Node.js/Express, base SQLite, frontend statique.
+
+> ℹ️ Le fichier `README.md` à la racine documente le **GitHub Copilot CLI** (outil de développement intégré à ce dépôt). Ce fichier `EVODRON.md` documente le **produit EVODRON** lui-même.
+
+---
+
+## Architecture
+
+```
+evodron/
+├── app.js # Point d'entrée Express
+├── public/ # Frontend statique (HTML/CSS/JS)
+│ ├── index.html
+│ ├── login.html
+│ ├── register.html
+│ ├── dashboard.html
+│ ├── referral.html
+│ ├── css/style.css
+│ └── js/referral.js
+├── src/
+│ ├── config/
+│ │ └── rewards.js # Configuration des récompenses
+│ ├── db/
+│ │ ├── database.js # Connexion SQLite (better-sqlite3)
+│ │ └── schema.sql # Schéma de la base de données
+│ ├── middleware/
+│ │ ├── auth.js # Vérification JWT
+│ │ └── rateLimiter.js # Rate limiting par IP
+│ ├── models/
+│ │ ├── user.js # Modèle utilisateur
+│ │ ├── referral.js # Modèle parrainage
+│ │ └── reward.js # Modèle récompenses
+│ └── routes/
+│ ├── auth.js # /api/auth (register, login)
+│ ├── health.js # /api/health
+│ └── referral.js # /api/referral (link, stats, rewards, activate-use)
+└── tests/
+ ├── referral.test.js # Tests flux de parrainage
+ └── anti-abuse.test.js # Tests anti-fraude
+```
+
+## Prérequis
+
+- **Node.js** >= 18
+- **npm** >= 9
+
+## Installation
+
+```bash
+git clone https://github.com/julesdemangeot-ship-it/EVODRON.git
+cd EVODRON
+npm install
+cp .env.example .env
+# Éditer .env et définir JWT_SECRET
+```
+
+## Démarrage
+
+```bash
+JWT_SECRET=votre-clé-secrète npm start
+# ou avec le fichier .env :
+npm start
+```
+
+Le serveur écoute sur `http://localhost:3000` (configurable via `PORT`).
+
+## Tests
+
+```bash
+npm test
+```
+
+Tous les tests utilisent une base SQLite en mémoire (`DB_PATH=:memory:`). Aucune configuration supplémentaire n'est requise.
+
+## API
+
+### Authentification
+
+| Méthode | Endpoint | Description |
+|---------|----------|-------------|
+| `POST` | `/api/auth/register` | Créer un compte (avec code de parrainage optionnel) |
+| `POST` | `/api/auth/login` | Se connecter, obtenir un token JWT |
+
+### Parrainage
+
+| Méthode | Endpoint | Auth | Description |
+|---------|----------|------|-------------|
+| `GET` | `/api/referral/link` | ✅ | Obtenir son lien de parrainage |
+| `GET` | `/api/referral/stats` | ✅ | Statistiques de parrainage |
+| `GET` | `/api/referral/rewards` | ✅ | Historique et récompenses disponibles |
+| `POST` | `/api/referral/claim-reward/:id` | ✅ | Réclamer une récompense |
+| `POST` | `/api/referral/activate-use` | ✅ | Déclarer la première utilisation active |
+| `GET` | `/api/referral/program-info` | ❌ | Conditions du programme (public) |
+
+### Santé
+
+| Méthode | Endpoint | Description |
+|---------|----------|-------------|
+| `GET` | `/api/health` | État de l'application et de la base de données |
+
+### Authentification JWT
+
+Passer le token dans le header `Authorization: ****** ou dans un cookie `token`.
+
+## Variables d'environnement
+
+Voir `.env.example` pour la liste complète.
+
+| Variable | Obligatoire | Défaut | Description |
+|----------|-------------|--------|-------------|
+| `JWT_SECRET` | ✅ | — | Clé secrète JWT |
+| `JWT_EXPIRY` | ❌ | `7d` | Durée de validité du token |
+| `PORT` | ❌ | `3000` | Port d'écoute |
+| `APP_URL` | ❌ | détecté | URL de base pour les liens de parrainage |
+| `DB_PATH` | ❌ | `./evodron.db` | Chemin du fichier SQLite |
+| `NODE_ENV` | ❌ | `development` | Environnement d'exécution |
+
+## Déploiement Docker
+
+```bash
+# Copier et éditer les variables
+cp .env.example .env
+# Démarrer
+docker compose up -d
+```
+
+## Flux de parrainage
+
+```
+Alice s'inscrit → obtient un code de parrainage unique
+ ↓
+Alice partage son lien : /register?ref=ABCD1234
+ ↓
+Bob s'inscrit avec ce lien → reçoit un bonus de bienvenue (10 crédits)
+ ↓
+Bob effectue sa première action active → POST /api/referral/activate-use
+ ↓
+Alice reçoit sa récompense de parrain (20 crédits)
+```
+
+## Sécurité
+
+- Mots de passe hachés avec **bcrypt** (coût 12)
+- Tokens JWT signés (HS256)
+- Rate limiting : 10 req/15 min sur `/api/auth`, 100 req/min sur `/api/referral`
+- Auto-parrainage interdit (vérification modèle + contrainte DB)
+- Un utilisateur ne peut avoir qu'un seul parrain (contrainte UNIQUE en base)
+- Pas de récompense sans activation effective du filleul
+
+## Licence
+
+Le code source EVODRON (dossiers `src/`, `public/`, `tests/`, fichiers `app.js`, `package.json`) est propriétaire.
+
+Le fichier `README.md`, `install.sh`, `changelog.md` et `LICENSE.md` sont des fichiers hérités du **GitHub Copilot CLI** distribués sous leur propre licence (voir `LICENSE.md`).
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..32c34018
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,26 @@
+# Politique de sécurité — Evodron
+
+## Signaler une vulnérabilité
+
+Si vous découvrez une vulnérabilité de sécurité dans Evodron, **ne l'ouvrez pas publiquement** en tant qu'issue GitHub.
+
+Contactez directement le mainteneur via la fonctionnalité **"Report a vulnerability"** de GitHub (onglet "Security" du dépôt) ou par email privé.
+
+Nous nous engageons à :
+- Accuser réception sous 48 heures.
+- Fournir un correctif ou un plan d'action sous 7 jours pour les vulnérabilités critiques.
+- Créditer le rapporteur dans le changelog si souhaité.
+
+## Versions supportées
+
+| Version | Support sécurité |
+|---------|-----------------|
+| 1.x | ✅ Oui |
+
+## Bonnes pratiques intégrées
+
+- Mots de passe hachés avec **bcrypt** (coût 12)
+- Tokens JWT signés HS256 avec expiration
+- Rate limiting sur toutes les routes d'authentification
+- Protection anti-auto-parrainage (modèle + contrainte DB)
+- Variables sensibles jamais commitées (`.env` dans `.gitignore`)
diff --git a/app.js b/app.js
index 9b48f3cc..f2704645 100644
--- a/app.js
+++ b/app.js
@@ -6,6 +6,8 @@ const path = require('path');
const authRoutes = require('./src/routes/auth');
const referralRoutes = require('./src/routes/referral');
+const healthRoutes = require('./src/routes/health');
+const { authLimiter, apiLimiter } = require('./src/middleware/rateLimiter');
const app = express();
const PORT = process.env.PORT || 3000;
@@ -18,9 +20,12 @@ app.use(cookieParser());
// Serve static frontend files
app.use(express.static(path.join(__dirname, 'public')));
+// Health check (no rate limit)
+app.use('/api/health', healthRoutes);
+
// API routes
-app.use('/api/auth', authRoutes);
-app.use('/api/referral', referralRoutes);
+app.use('/api/auth', authLimiter, authRoutes);
+app.use('/api/referral', apiLimiter, referralRoutes);
// Catch-all: serve index.html for client-side navigation
app.get('*', (req, res) => {
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..9636c96d
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,22 @@
+services:
+ app:
+ build: .
+ ports:
+ - "3000:3000"
+ environment:
+ - JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required}
+ - JWT_EXPIRY=${JWT_EXPIRY:-7d}
+ - APP_URL=${APP_URL:-http://localhost:3000}
+ - NODE_ENV=${NODE_ENV:-production}
+ volumes:
+ - evodron_data:/data
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
+ interval: 30s
+ timeout: 5s
+ retries: 3
+ start_period: 10s
+
+volumes:
+ evodron_data:
diff --git a/package-lock.json b/package-lock.json
index c19cdd83..098046cf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"better-sqlite3": "^9.4.3",
"cookie-parser": "^1.4.6",
"express": "^4.18.2",
+ "express-rate-limit": "^8.6.2",
"jsonwebtoken": "^9.0.2",
"nanoid": "^3.3.7"
},
@@ -2251,6 +2252,48 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/express-rate-limit": {
+ "version": "8.6.2",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.6.2.tgz",
+ "integrity": "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "ip-address": "^10.2.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": ">= 4.11"
+ }
+ },
+ "node_modules/express-rate-limit/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/express-rate-limit/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/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",
@@ -2714,6 +2757,15 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"license": "ISC"
},
+ "node_modules/ip-address": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz",
+ "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
diff --git a/package.json b/package.json
index 5a1aa746..4cd7e24d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
- "name": "evodron-referral",
+ "name": "evodron",
"version": "1.0.0",
- "description": "Evodron Referral Program — backend and frontend",
+ "description": "Evodron — Plateforme de parrainage (backend Node.js/Express + SQLite)",
"main": "app.js",
"scripts": {
"start": "node app.js",
@@ -13,6 +13,7 @@
"better-sqlite3": "^9.4.3",
"cookie-parser": "^1.4.6",
"express": "^4.18.2",
+ "express-rate-limit": "^8.6.2",
"jsonwebtoken": "^9.0.2",
"nanoid": "^3.3.7"
},
diff --git a/src/middleware/rateLimiter.js b/src/middleware/rateLimiter.js
new file mode 100644
index 00000000..47d74cdf
--- /dev/null
+++ b/src/middleware/rateLimiter.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const rateLimit = require('express-rate-limit');
+
+/**
+ * Strict rate limiter for authentication endpoints.
+ * 10 requests per 15-minute window per IP.
+ */
+const authLimiter = rateLimit({
+ windowMs: 15 * 60 * 1000, // 15 minutes
+ max: 10,
+ standardHeaders: 'draft-7',
+ legacyHeaders: false,
+ message: { error: 'Too many requests, please try again later.' },
+ skip: () => process.env.NODE_ENV === 'test',
+});
+
+/**
+ * General API rate limiter.
+ * 100 requests per 1-minute window per IP.
+ */
+const apiLimiter = rateLimit({
+ windowMs: 60 * 1000, // 1 minute
+ max: 100,
+ standardHeaders: 'draft-7',
+ legacyHeaders: false,
+ message: { error: 'Too many requests, please try again later.' },
+ skip: () => process.env.NODE_ENV === 'test',
+});
+
+module.exports = { authLimiter, apiLimiter };
diff --git a/src/routes/health.js b/src/routes/health.js
new file mode 100644
index 00000000..54b1e0db
--- /dev/null
+++ b/src/routes/health.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const express = require('express');
+const { getDb } = require('../db/database');
+
+const router = express.Router();
+
+/**
+ * GET /api/health
+ * Returns the application health status.
+ * No authentication required — used by load balancers and monitoring.
+ */
+router.get('/', (req, res) => {
+ const status = { status: 'ok', version: process.env.npm_package_version || '1.0.0', timestamp: new Date().toISOString() };
+
+ try {
+ getDb().prepare('SELECT 1').get();
+ status.db = 'ok';
+ } catch {
+ status.db = 'error';
+ status.status = 'degraded';
+ }
+
+ const code = status.status === 'ok' ? 200 : 503;
+ return res.status(code).json(status);
+});
+
+module.exports = router;
diff --git a/tests/health.test.js b/tests/health.test.js
new file mode 100644
index 00000000..3fc59f18
--- /dev/null
+++ b/tests/health.test.js
@@ -0,0 +1,17 @@
+'use strict';
+
+process.env.JWT_SECRET = 'test-secret-do-not-use-in-production';
+process.env.DB_PATH = ':memory:';
+
+const request = require('supertest');
+const app = require('../app');
+
+describe('GET /api/health', () => {
+ test('returns 200 with status ok and db ok', async () => {
+ const res = await request(app).get('/api/health');
+ expect(res.status).toBe(200);
+ expect(res.body.status).toBe('ok');
+ expect(res.body.db).toBe('ok');
+ expect(res.body).toHaveProperty('timestamp');
+ });
+});
From 1184d605504aa38150ca03210b10117a1a9aa0f4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:00:11 +0000
Subject: [PATCH 03/13] =?UTF-8?q?feat:=20add=20EVODRON=20platform=20?=
=?UTF-8?q?=E2=80=94=20API,=20CLI,=20DB,=20referral/rewards/stats=20system?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Phase 1: monorepo workspace setup (evodron/)
- Phase 2: CLI wrapper with Commander.js + splash screen + auth/referral/rewards/stats commands
- Phase 3: Fastify API with JWT auth, rate limiting, CORS
- Phase 4: User accounts with JWT + refresh tokens, bcrypt password hashing
- Phase 5: Referral system with anti-abuse, self-referral prevention, IP tracking
- Phase 6: Virtual credits reward system with configurable rules
- Phase 7: Stats endpoints + abuse flags admin API
- Phase 8: 24 passing tests (unit + integration)
- Docs: ARCHITECTURE.md, THIRD_PARTY.md, EVODRON.md, .env.example
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
evodron/.env.example | 52 +
evodron/.gitignore | 9 +
evodron/docs/ARCHITECTURE.md | 102 +
evodron/docs/EVODRON.md | 178 +
evodron/docs/THIRD_PARTY.md | 49 +
evodron/package-lock.json | 5292 +++++++++++++++++
evodron/package.json | 29 +
evodron/packages/api/:memory:?cache=shared | Bin 0 -> 4096 bytes
.../packages/api/:memory:?cache=shared-shm | Bin 0 -> 32768 bytes
.../packages/api/:memory:?cache=shared-wal | 0
evodron/packages/api/package.json | 33 +
.../packages/api/src/__tests__/api.test.ts | 314 +
.../api/src/__tests__/unit/helpers.test.ts | 60 +
evodron/packages/api/src/index.ts | 85 +
evodron/packages/api/src/middleware/auth.ts | 27 +
.../packages/api/src/middleware/helpers.ts | 35 +
evodron/packages/api/src/routes/admin.ts | 102 +
evodron/packages/api/src/routes/auth.ts | 327 +
evodron/packages/api/src/routes/referrals.ts | 109 +
evodron/packages/api/src/routes/rewards.ts | 58 +
evodron/packages/api/src/routes/sessions.ts | 243 +
evodron/packages/api/src/routes/stats.ts | 52 +
evodron/packages/api/src/routes/users.ts | 70 +
evodron/packages/api/tsconfig.json | 19 +
evodron/packages/api/vitest.config.mts | 15 +
evodron/packages/cli/package.json | 29 +
evodron/packages/cli/src/bin/evodron.ts | 27 +
evodron/packages/cli/src/commands/auth.ts | 153 +
evodron/packages/cli/src/commands/referral.ts | 70 +
evodron/packages/cli/src/commands/rewards.ts | 67 +
evodron/packages/cli/src/commands/run.ts | 116 +
evodron/packages/cli/src/commands/stats.ts | 35 +
evodron/packages/cli/src/services/api.ts | 71 +
evodron/packages/cli/src/services/config.ts | 49 +
evodron/packages/cli/src/ui/splash.ts | 24 +
evodron/packages/cli/tsconfig.json | 18 +
evodron/packages/db/package.json | 23 +
evodron/packages/db/src/client.ts | 23 +
evodron/packages/db/src/index.ts | 2 +
evodron/packages/db/src/migrate.ts | 103 +
evodron/packages/db/src/schema.ts | 101 +
evodron/packages/db/src/seed.ts | 53 +
evodron/packages/db/tsconfig.json | 16 +
evodron/packages/shared/package.json | 17 +
evodron/packages/shared/src/index.ts | 120 +
evodron/packages/shared/tsconfig.json | 16 +
evodron/scripts/setup.sh | 73 +
47 files changed, 8466 insertions(+)
create mode 100644 evodron/.env.example
create mode 100644 evodron/.gitignore
create mode 100644 evodron/docs/ARCHITECTURE.md
create mode 100644 evodron/docs/EVODRON.md
create mode 100644 evodron/docs/THIRD_PARTY.md
create mode 100644 evodron/package-lock.json
create mode 100644 evodron/package.json
create mode 100644 evodron/packages/api/:memory:?cache=shared
create mode 100644 evodron/packages/api/:memory:?cache=shared-shm
create mode 100644 evodron/packages/api/:memory:?cache=shared-wal
create mode 100644 evodron/packages/api/package.json
create mode 100644 evodron/packages/api/src/__tests__/api.test.ts
create mode 100644 evodron/packages/api/src/__tests__/unit/helpers.test.ts
create mode 100644 evodron/packages/api/src/index.ts
create mode 100644 evodron/packages/api/src/middleware/auth.ts
create mode 100644 evodron/packages/api/src/middleware/helpers.ts
create mode 100644 evodron/packages/api/src/routes/admin.ts
create mode 100644 evodron/packages/api/src/routes/auth.ts
create mode 100644 evodron/packages/api/src/routes/referrals.ts
create mode 100644 evodron/packages/api/src/routes/rewards.ts
create mode 100644 evodron/packages/api/src/routes/sessions.ts
create mode 100644 evodron/packages/api/src/routes/stats.ts
create mode 100644 evodron/packages/api/src/routes/users.ts
create mode 100644 evodron/packages/api/tsconfig.json
create mode 100644 evodron/packages/api/vitest.config.mts
create mode 100644 evodron/packages/cli/package.json
create mode 100644 evodron/packages/cli/src/bin/evodron.ts
create mode 100644 evodron/packages/cli/src/commands/auth.ts
create mode 100644 evodron/packages/cli/src/commands/referral.ts
create mode 100644 evodron/packages/cli/src/commands/rewards.ts
create mode 100644 evodron/packages/cli/src/commands/run.ts
create mode 100644 evodron/packages/cli/src/commands/stats.ts
create mode 100644 evodron/packages/cli/src/services/api.ts
create mode 100644 evodron/packages/cli/src/services/config.ts
create mode 100644 evodron/packages/cli/src/ui/splash.ts
create mode 100644 evodron/packages/cli/tsconfig.json
create mode 100644 evodron/packages/db/package.json
create mode 100644 evodron/packages/db/src/client.ts
create mode 100644 evodron/packages/db/src/index.ts
create mode 100644 evodron/packages/db/src/migrate.ts
create mode 100644 evodron/packages/db/src/schema.ts
create mode 100644 evodron/packages/db/src/seed.ts
create mode 100644 evodron/packages/db/tsconfig.json
create mode 100644 evodron/packages/shared/package.json
create mode 100644 evodron/packages/shared/src/index.ts
create mode 100644 evodron/packages/shared/tsconfig.json
create mode 100755 evodron/scripts/setup.sh
diff --git a/evodron/.env.example b/evodron/.env.example
new file mode 100644
index 00000000..0515a2d3
--- /dev/null
+++ b/evodron/.env.example
@@ -0,0 +1,52 @@
+# EVODRON — Environment Variables
+
+# Copy this file to .env and fill in real values.
+# NEVER commit .env to version control.
+
+# ─── API Server ──────────────────────────────────────────────────────────────
+
+# Secret used to sign JWTs. Must be a long, random string (32+ chars).
+EVODRON_JWT_SECRET=change-me-to-a-long-random-secret
+
+# Secret used to sign refresh tokens (different from JWT secret).
+EVODRON_REFRESH_SECRET=change-me-to-another-long-random-secret
+
+# Port the API listens on.
+EVODRON_API_PORT=3000
+
+# Host the API binds to.
+EVODRON_API_HOST=0.0.0.0
+
+# ─── Database ────────────────────────────────────────────────────────────────
+
+# SQLite: file path (development / small production)
+EVODRON_DB_URL=file:./evodron.db
+
+# PostgreSQL: connection string (large production)
+# EVODRON_DB_URL=******host:5432/evodron
+
+# ─── Referral System ─────────────────────────────────────────────────────────
+
+# Public base URL for referral links (no trailing slash).
+EVODRON_REFERRAL_BASE_URL=https://evodron.io
+
+# Minimum number of completed sessions before a referral is considered "active"
+# and rewards are triggered.
+EVODRON_REWARD_MIN_SESSIONS=3
+
+# ─── CLI ─────────────────────────────────────────────────────────────────────
+
+# URL of the EVODRON API that the CLI communicates with.
+EVODRON_API_URL=http://localhost:3000
+
+# Path to the local config directory (defaults to ~/.evodron if not set).
+# EVODRON_CONFIG_DIR=~/.evodron
+
+# ─── Environment ─────────────────────────────────────────────────────────────
+
+NODE_ENV=development
+
+# ─── Logging ─────────────────────────────────────────────────────────────────
+
+# Log level: trace | debug | info | warn | error | fatal
+LOG_LEVEL=info
diff --git a/evodron/.gitignore b/evodron/.gitignore
new file mode 100644
index 00000000..9e1d8af9
--- /dev/null
+++ b/evodron/.gitignore
@@ -0,0 +1,9 @@
+node_modules/
+dist/
+*.js.map
+.env
+*.db
+*.db-journal
+*.log
+coverage/
+.nyc_output/
diff --git a/evodron/docs/ARCHITECTURE.md b/evodron/docs/ARCHITECTURE.md
new file mode 100644
index 00000000..b1ce1927
--- /dev/null
+++ b/evodron/docs/ARCHITECTURE.md
@@ -0,0 +1,102 @@
+# EVODRON Architecture
+
+## Overview
+
+EVODRON is an AI-powered developer platform that orchestrates the GitHub Copilot CLI to deliver a richer, identity-branded experience with user accounts, referral programmes, reward credits, and usage statistics.
+
+```
+┌──────────────────────────────────────────────────────────┐
+│ USER │
+│ evodron │
+└──────────────────────┬───────────────────────────────────┘
+ │
+┌──────────────────────▼───────────────────────────────────┐
+│ EVODRON CLI WRAPPER (packages/cli) │
+│ • Splash screen / branding │
+│ • Local config (~/.evodron/config.json) │
+│ • Auth token management │
+│ • Usage metrics (local, with consent) │
+│ • Delegates to GitHub Copilot CLI for AI tasks │
+└──────┬───────────────────────────────────────────────────┘
+ │ HTTPS (JWT)
+┌──────▼───────────────────────────────────────────────────┐
+│ EVODRON API (packages/api) │
+│ │
+│ Routes: │
+│ POST /auth/register — create account │
+│ POST /auth/login — get JWT + refresh token │
+│ POST /auth/refresh — rotate JWT │
+│ GET /users/me — profile + credits │
+│ GET /referrals/code — my referral code/link │
+│ GET /referrals/stats — referrals dashboard │
+│ POST /sessions/start — log session start │
+│ POST /sessions/end — log session end │
+│ GET /rewards — reward history │
+│ GET /stats — usage statistics │
+│ GET /admin/abuse-flags — abuse management (admin) │
+│ │
+│ Middleware: │
+│ • JWT authentication │
+│ • Rate limiting (per IP + per user) │
+│ • Anti-abuse detection │
+└──────┬───────────────────────────────────────────────────┘
+ │ Drizzle ORM
+┌──────▼───────────────────────────────────────────────────┐
+│ DATABASE (packages/db) │
+│ │
+│ SQLite (development / small production) │
+│ PostgreSQL (large production — swap DB_URL) │
+│ │
+│ Tables: │
+│ users — accounts, referral codes │
+│ sessions — usage tracking per user │
+│ referrals — parrain→filleul relationships │
+│ rewards — credit ledger │
+│ reward_rules — configurable reward triggers │
+│ abuse_flags — fraud/abuse detection records │
+│ ip_registry — IP tracking for anti-fraud │
+└──────────────────────────────────────────────────────────┘
+```
+
+## Packages
+
+### `packages/shared`
+TypeScript types and Zod schemas shared between CLI and API packages. Zero runtime dependencies beyond `zod`.
+
+### `packages/db`
+Drizzle ORM schema definitions and migrations. Supports SQLite (via `better-sqlite3`) in development and small deployments, and PostgreSQL (via `postgres`) in production — controlled by `DB_URL`.
+
+### `packages/api`
+Fastify-based REST API. Handles authentication (JWT), referrals, rewards, sessions, stats, and abuse detection. All routes are rate-limited. Auth-required routes validate JWT on every request.
+
+### `packages/cli`
+The `evodron` CLI wrapper. Provides the branded entry point. Handles local config, authentication against the API, and delegates AI coding tasks to the GitHub Copilot CLI binary. Collects opt-in usage metrics.
+
+## Security considerations
+
+- Passwords are hashed with bcrypt (cost factor 12).
+- JWTs expire after 15 minutes; refresh tokens after 30 days.
+- Refresh tokens are stored hashed in the database; rotation invalidates the old token.
+- Rate limiting: 100 req/min per IP globally; 20 req/min on auth endpoints.
+- Anti-abuse: IP deduplication, self-referral prevention, minimum activity threshold before reward.
+- No API keys, secrets, or passwords are ever stored in the codebase.
+
+## Referral system
+
+1. Each registered user receives a unique 8-character alphanumeric referral code.
+2. A shareable link is derived from `EVODRON_REFERRAL_BASE_URL/ref/`.
+3. When a new user registers with `?ref=`, the `referrals` row is created with status `pending`.
+4. After the referee reaches `EVODRON_REWARD_MIN_SESSIONS` active sessions, status becomes `active`.
+5. Reward credits are credited to both referee and referrer via the configurable `reward_rules`.
+
+## Reward system (virtual credits only)
+
+- Credits are a **virtual, internal unit** with no monetary value.
+- Reward rules are stored in the `reward_rules` table and can be updated without code changes.
+- Default rules: referrer receives 100 credits per active referee; referee receives 50 onboarding credits.
+- No cash-out, fiat conversion, or financial features are implemented.
+- Any future financial feature would require legal, fiscal, and payment compliance work first.
+
+## EVODRON is not affiliated with GitHub or Microsoft
+
+The GitHub Copilot CLI is a third-party binary component. See `THIRD_PARTY.md`.
diff --git a/evodron/docs/EVODRON.md b/evodron/docs/EVODRON.md
new file mode 100644
index 00000000..e92b19a9
--- /dev/null
+++ b/evodron/docs/EVODRON.md
@@ -0,0 +1,178 @@
+# EVODRON
+
+EVODRON is an AI-powered developer platform that enriches the GitHub Copilot CLI experience with user accounts, a referral programme, reward credits, usage statistics, and anti-abuse protection.
+
+> **Disclaimer:** EVODRON is not affiliated with, endorsed by, or officially connected to GitHub, Inc. or Microsoft Corporation. The GitHub Copilot CLI is a separate, third-party binary component. See [THIRD_PARTY.md](./THIRD_PARTY.md).
+
+---
+
+## Features
+
+- **Evodron identity** — branded CLI with splash screen and EVODRON visual identity
+- **User accounts** — registration, login, JWT authentication, profile management
+- **Referral programme** — unique codes, shareable links, tracking, and anti-abuse
+- **Reward credits** — virtual credits with configurable rules (no monetary value)
+- **Usage statistics** — sessions, commands, credit history, level system
+- **Anti-abuse** — IP tracking, self-referral prevention, fraud detection, rate limiting
+- **Admin tools** — manage abuse flags, ban users, configure reward rules
+
+---
+
+## Quick Start
+
+### Prerequisites
+
+- Node.js >= 18
+- (Optional) GitHub Copilot CLI for AI features — install with `curl -fsSL https://gh.io/copilot-install | bash`
+
+### Setup
+
+```bash
+cd evodron
+bash scripts/setup.sh
+```
+
+Then edit `.env` to set a secure `EVODRON_JWT_SECRET`.
+
+### Start the API
+
+```bash
+npm run dev:api
+```
+
+### Build and use the CLI
+
+```bash
+npm run build
+node packages/cli/dist/bin/evodron.js --help
+```
+
+### Register an account
+
+```bash
+evodron auth register
+```
+
+### Launch AI assistant (delegates to GitHub Copilot CLI)
+
+```bash
+evodron run -- "explain this code"
+```
+
+---
+
+## CLI Commands
+
+| Command | Description |
+|---------|-------------|
+| `evodron auth register` | Create a new EVODRON account |
+| `evodron auth login` | Log in |
+| `evodron auth logout` | Log out |
+| `evodron auth status` | Show login status |
+| `evodron referral code` | Show your referral code and link |
+| `evodron referral stats` | Show referral dashboard |
+| `evodron rewards history` | Show reward credit history |
+| `evodron rewards rules` | Show active reward rules |
+| `evodron stats` | Show usage statistics |
+| `evodron run [args...]` | Launch GitHub Copilot CLI (third-party) |
+
+---
+
+## API Endpoints
+
+| Method | Path | Auth | Description |
+|--------|------|------|-------------|
+| GET | `/health` | No | Health check |
+| POST | `/auth/register` | No | Register |
+| POST | `/auth/login` | No | Login |
+| POST | `/auth/refresh` | No | Refresh token |
+| POST | `/auth/logout` | No | Logout |
+| GET | `/users/me` | Yes | Get profile |
+| PATCH | `/users/me/consent` | Yes | Update metrics consent |
+| GET | `/referrals/code` | Yes | Get referral code |
+| GET | `/referrals/stats` | Yes | Referral dashboard |
+| POST | `/sessions/start` | Yes | Start session |
+| POST | `/sessions/end` | Yes | End session |
+| GET | `/rewards` | Yes | Reward history |
+| GET | `/rewards/rules` | Yes | Active reward rules |
+| GET | `/stats` | Yes | Usage stats |
+| GET | `/admin/abuse-flags` | Admin | Unresolved abuse flags |
+| POST | `/admin/abuse-flags/:id/resolve` | Admin | Resolve flag |
+| POST | `/admin/users/:id/ban` | Admin | Ban user |
+| GET | `/admin/reward-rules` | Admin | All reward rules |
+| PATCH | `/admin/reward-rules/:id` | Admin | Update reward rule |
+
+---
+
+## Referral Programme
+
+Each user receives a unique 8-character referral code and a shareable link.
+
+When a new user registers using a referral link:
+1. A `pending` referral is created linking referrer and referee.
+2. The referee receives onboarding credits immediately.
+3. After the referee completes `EVODRON_REWARD_MIN_SESSIONS` sessions, the referral becomes `active`.
+4. The referrer receives referral credits.
+
+**Anti-abuse measures:**
+- Self-referral is blocked (a user cannot use their own code).
+- Duplicate referrals are prevented (one referee → one referrer only).
+- IP tracking flags accounts created from the same IP address excessively.
+- Banned users' pending referrals are marked as fraud.
+- Rewards only trigger after verified usage (minimum sessions threshold).
+
+---
+
+## Reward System
+
+EVODRON credits are **virtual, internal units with no monetary value**. They cannot be exchanged for cash, goods, or services.
+
+| Level | Credits required |
+|-------|-----------------|
+| Bronze | 0 |
+| Silver | 300 |
+| Gold | 1 000 |
+
+Default reward rules:
+
+| Rule | Trigger | Credits |
+|------|---------|---------|
+| Referral (referrer) | Referee reaches active status | 100 |
+| Onboarding (referee) | Join via referral link | 50 |
+| Milestone | Complete 10 sessions | 25 |
+
+Rules are configurable via `PATCH /admin/reward-rules/:id` without code changes.
+
+> ⚠️ **Legal notice:** Any future conversion of credits to real money would require legal, fiscal, and payment compliance work (payment institution registration, KYC, GDPR compliance, tax obligations). This is intentionally **not implemented**.
+
+---
+
+## Environment Variables
+
+See `.env.example` for all available variables.
+
+| Variable | Required | Description |
+|----------|----------|-------------|
+| `EVODRON_JWT_SECRET` | Yes | JWT signing secret (32+ chars) |
+| `EVODRON_REFRESH_SECRET` | Yes | Refresh token secret |
+| `EVODRON_DB_URL` | Yes | SQLite path or PostgreSQL URL |
+| `EVODRON_API_URL` | CLI | API URL (used by CLI) |
+| `EVODRON_REFERRAL_BASE_URL` | No | Base URL for referral links |
+| `EVODRON_REWARD_MIN_SESSIONS` | No | Minimum sessions before referral activates (default: 3) |
+| `EVODRON_API_PORT` | No | API port (default: 3000) |
+| `NODE_ENV` | No | `development` or `production` |
+| `LOG_LEVEL` | No | Log level (default: `info`) |
+
+---
+
+## Architecture
+
+See [ARCHITECTURE.md](./ARCHITECTURE.md) for the full architecture diagram and package descriptions.
+
+---
+
+## Third-Party Components
+
+See [THIRD_PARTY.md](./THIRD_PARTY.md) for full attribution.
+
+The GitHub Copilot CLI is a third-party binary component by GitHub, Inc. EVODRON uses it as an optional, unmodified sub-component for AI coding features.
diff --git a/evodron/docs/THIRD_PARTY.md b/evodron/docs/THIRD_PARTY.md
new file mode 100644
index 00000000..80143935
--- /dev/null
+++ b/evodron/docs/THIRD_PARTY.md
@@ -0,0 +1,49 @@
+# Third-Party Component Attribution
+
+EVODRON includes or depends on the following third-party components.
+
+---
+
+## GitHub Copilot CLI
+
+- **Component**: GitHub Copilot CLI binary (`gh copilot` / `ghcs`)
+- **Source**: https://github.com/github/copilot-cli
+- **Author**: GitHub, Inc. (a subsidiary of Microsoft Corporation)
+- **License**: GitHub Copilot CLI License (see `../LICENSE.md`)
+
+### Important notices
+
+- EVODRON is **not affiliated with, endorsed by, or officially connected to GitHub, Inc. or Microsoft Corporation**.
+- The GitHub Copilot CLI is a **separate, unmodified binary** component redistributed as part of EVODRON in accordance with Section 2 of the GitHub Copilot CLI License.
+- EVODRON does **not** modify, adapt, translate, or create derivative works of the GitHub Copilot CLI.
+- EVODRON does **not** claim authorship of the GitHub Copilot CLI.
+- The GitHub Copilot CLI is distributed **only in unmodified form** and is not the primary product of EVODRON; it is one component among others.
+- All copyright, trademark, and attribution notices from the GitHub Copilot CLI are retained.
+
+The EVODRON platform — including its CLI wrapper, backend API, referral system, reward system, user accounts, and all other custom code — is original work independent of the GitHub Copilot CLI.
+
+---
+
+## Open Source Dependencies
+
+The following open-source packages are used by EVODRON's original codebase. Each is used under its respective license.
+
+| Package | License | Usage |
+|---------|---------|-------|
+| fastify | MIT | HTTP API server |
+| @fastify/jwt | MIT | JWT authentication plugin |
+| @fastify/rate-limit | MIT | Rate limiting |
+| @fastify/cors | MIT | CORS headers |
+| drizzle-orm | Apache-2.0 | Database ORM |
+| better-sqlite3 | MIT | SQLite driver |
+| commander | MIT | CLI argument parsing |
+| chalk | MIT | Terminal color output |
+| nanoid | MIT | Unique ID generation |
+| bcryptjs | MIT | Password hashing |
+| zod | MIT | Schema validation |
+| dotenv | BSD-2-Clause | Environment variable loading |
+| vitest | MIT | Unit and integration testing |
+| tsx | MIT | TypeScript execution |
+| typescript | Apache-2.0 | TypeScript compiler |
+
+Full license texts for these packages are available in each package's `node_modules` directory or at the respective project repositories.
diff --git a/evodron/package-lock.json b/evodron/package-lock.json
new file mode 100644
index 00000000..89230443
--- /dev/null
+++ b/evodron/package-lock.json
@@ -0,0 +1,5292 @@
+{
+ "name": "evodron",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "evodron",
+ "version": "0.1.0",
+ "license": "UNLICENSED",
+ "workspaces": [
+ "packages/*"
+ ],
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz",
+ "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==",
+ "deprecated": "Merged into tsx: https://tsx.hirok.io",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.18.20",
+ "source-map-support": "^0.5.21"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
+ "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
+ "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
+ "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
+ "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
+ "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
+ "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
+ "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
+ "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
+ "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
+ "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
+ "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
+ "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
+ "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
+ "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
+ "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
+ "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
+ "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
+ "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
+ "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
+ "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
+ "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
+ "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": {
+ "version": "0.18.20",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
+ "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.18.20",
+ "@esbuild/android-arm64": "0.18.20",
+ "@esbuild/android-x64": "0.18.20",
+ "@esbuild/darwin-arm64": "0.18.20",
+ "@esbuild/darwin-x64": "0.18.20",
+ "@esbuild/freebsd-arm64": "0.18.20",
+ "@esbuild/freebsd-x64": "0.18.20",
+ "@esbuild/linux-arm": "0.18.20",
+ "@esbuild/linux-arm64": "0.18.20",
+ "@esbuild/linux-ia32": "0.18.20",
+ "@esbuild/linux-loong64": "0.18.20",
+ "@esbuild/linux-mips64el": "0.18.20",
+ "@esbuild/linux-ppc64": "0.18.20",
+ "@esbuild/linux-riscv64": "0.18.20",
+ "@esbuild/linux-s390x": "0.18.20",
+ "@esbuild/linux-x64": "0.18.20",
+ "@esbuild/netbsd-x64": "0.18.20",
+ "@esbuild/openbsd-x64": "0.18.20",
+ "@esbuild/sunos-x64": "0.18.20",
+ "@esbuild/win32-arm64": "0.18.20",
+ "@esbuild/win32-ia32": "0.18.20",
+ "@esbuild/win32-x64": "0.18.20"
+ }
+ },
+ "node_modules/@esbuild-kit/esm-loader": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",
+ "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==",
+ "deprecated": "Merged into tsx: https://tsx.hirok.io",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@esbuild-kit/core-utils": "^3.3.2",
+ "get-tsconfig": "^4.7.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
+ "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz",
+ "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz",
+ "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz",
+ "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz",
+ "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz",
+ "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz",
+ "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz",
+ "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz",
+ "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz",
+ "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz",
+ "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz",
+ "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz",
+ "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz",
+ "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz",
+ "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz",
+ "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz",
+ "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz",
+ "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz",
+ "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
+ "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz",
+ "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz",
+ "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz",
+ "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz",
+ "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@evodron/api": {
+ "resolved": "packages/api",
+ "link": true
+ },
+ "node_modules/@evodron/cli": {
+ "resolved": "packages/cli",
+ "link": true
+ },
+ "node_modules/@evodron/db": {
+ "resolved": "packages/db",
+ "link": true
+ },
+ "node_modules/@evodron/shared": {
+ "resolved": "packages/shared",
+ "link": true
+ },
+ "node_modules/@fastify/ajv-compiler": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.6.tgz",
+ "integrity": "sha512-NtuzM0SfaMJbGlnjr9LWQUN5LzgSrbB8tf/wRZNas+4E1O/Nmzl53e7ruT61HDZyRCJGC6FxIogmNZO1c5ETBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.12.0",
+ "ajv-formats": "^3.0.1",
+ "fast-uri": "^4.0.0"
+ }
+ },
+ "node_modules/@fastify/cors": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-10.1.0.tgz",
+ "integrity": "sha512-MZyBCBJtII60CU9Xme/iE4aEy8G7QpzGR8zkdXZkDFt7ElEMachbE61tfhAG/bvSaULlqlf0huMT12T7iqEmdQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "fastify-plugin": "^5.0.0",
+ "mnemonist": "0.40.0"
+ }
+ },
+ "node_modules/@fastify/error": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.2.0.tgz",
+ "integrity": "sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@fastify/fast-json-stringify-compiler": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.1.0.tgz",
+ "integrity": "sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "fast-json-stringify": "^7.0.0"
+ }
+ },
+ "node_modules/@fastify/forwarded": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.2.tgz",
+ "integrity": "sha512-NE8HgKLgYejV9lDpqkEFaDKMLYelJBVfHekhB0UKvX0ghagXRJqg68feg8er1NPXxG4N9i6vPxzt8E+3wHfcmA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@fastify/jwt": {
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/@fastify/jwt/-/jwt-10.2.1.tgz",
+ "integrity": "sha512-8FHalB082a6HFj+neP9TdJZrUa65Aq6mtozVjd3vH3Yy7hmjRJUDKLPdxYRYF9S077JeN9RgimsautqnijbDlQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/error": "^4.2.0",
+ "@lukeed/ms": "^2.0.2",
+ "fast-jwt": "^6.2.4",
+ "fastify-plugin": "^6.0.0",
+ "steed": "^1.1.3"
+ }
+ },
+ "node_modules/@fastify/jwt/node_modules/fastify-plugin": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-6.0.0.tgz",
+ "integrity": "sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@fastify/merge-json-schemas": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz",
+ "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/@fastify/proxy-addr": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.1.0.tgz",
+ "integrity": "sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/forwarded": "^3.0.0",
+ "ipaddr.js": "^2.1.0"
+ }
+ },
+ "node_modules/@fastify/rate-limit": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@fastify/rate-limit/-/rate-limit-10.3.0.tgz",
+ "integrity": "sha512-eIGkG9XKQs0nyynatApA3EVrojHOuq4l6fhB4eeCk4PIOeadvOJz9/4w3vGI44Go17uaXOWEcPkaD8kuKm7g6Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@lukeed/ms": "^2.0.2",
+ "fastify-plugin": "^5.0.0",
+ "toad-cache": "^3.7.0"
+ }
+ },
+ "node_modules/@hono/node-server": {
+ "version": "1.19.17",
+ "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.17.tgz",
+ "integrity": "sha512-dSneS5qhiauZWGDCeK4o695Xd9nUNjviSZCMQrj10eetr8Uln1ucn6bbphOM6UynAMMtNIzZNSpL9vnASJwrPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.14.1"
+ },
+ "peerDependencies": {
+ "hono": "^4"
+ }
+ },
+ "node_modules/@hono/zod-validator": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@hono/zod-validator/-/zod-validator-0.2.2.tgz",
+ "integrity": "sha512-dSDxaPV70Py8wuIU2QNpoVEIOSzSXZ/6/B/h4xA7eOMz7+AarKTSGV8E6QwrdcCbBLkpqfJ4Q2TmBO0eP1tCBQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "hono": ">=3.9.0",
+ "zod": "^3.19.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@lukeed/ms": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz",
+ "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.143.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz",
+ "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@pinojs/redact": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
+ "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
+ "license": "MIT"
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz",
+ "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz",
+ "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz",
+ "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz",
+ "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz",
+ "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz",
+ "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz",
+ "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz",
+ "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz",
+ "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz",
+ "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz",
+ "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz",
+ "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz",
+ "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz",
+ "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/bcryptjs": {
+ "version": "2.4.6",
+ "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz",
+ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/better-sqlite3": {
+ "version": "7.6.13",
+ "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz",
+ "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "20.19.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz",
+ "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
+ "node_modules/@vitest/expect": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz",
+ "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.1.0",
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "chai": "^6.2.2",
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz",
+ "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/runner": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz",
+ "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "4.1.10",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz",
+ "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "magic-string": "^0.30.21",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz",
+ "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz",
+ "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "4.1.10",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/abstract-logging": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
+ "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==",
+ "license": "MIT"
+ },
+ "node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
+ "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv/node_modules/fast-uri": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
+ "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+ "license": "MIT",
+ "dependencies": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/atomic-sleep": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+ "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/avvio": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.3.0.tgz",
+ "integrity": "sha512-g2tQ7LE7oOSqDfwEm3M+ZCMTJc7KiZCdJ4UwyZJb5ckTKyYu50OYmvv0mCFXPuYXoM4zkSt8zM9XQ9KCvxA74A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/error": "^4.0.0",
+ "fastq": "^1.17.1"
+ }
+ },
+ "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==",
+ "dev": true,
+ "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/bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
+ "license": "MIT"
+ },
+ "node_modules/better-sqlite3": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.6.0.tgz",
+ "integrity": "sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "prebuild-install": "^7.1.1"
+ }
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bn.js": {
+ "version": "4.12.5",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.5.tgz",
+ "integrity": "sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz",
+ "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/camelcase": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz",
+ "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/chai": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
+ "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "license": "ISC"
+ },
+ "node_modules/cli-color": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz",
+ "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "d": "^1.0.1",
+ "es5-ext": "^0.10.64",
+ "es6-iterator": "^2.0.3",
+ "memoizee": "^0.4.15",
+ "timers-ext": "^0.1.7"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "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/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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/copy-anything": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz",
+ "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-what": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/d": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
+ "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "es5-ext": "^0.10.64",
+ "type": "^2.7.2"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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/difflib": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz",
+ "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==",
+ "dev": true,
+ "dependencies": {
+ "heap": ">= 0.2.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "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/dreamopt": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz",
+ "integrity": "sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==",
+ "dev": true,
+ "dependencies": {
+ "wordwrap": ">=0.0.2"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/drizzle-kit": {
+ "version": "0.20.18",
+ "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.20.18.tgz",
+ "integrity": "sha512-fLTwcnLqtBxGd+51H/dEm9TC0FW6+cIX/RVPyNcitBO77X9+nkogEfMAJebpd/8Yl4KucmePHRYRWWvUlW0rqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@esbuild-kit/esm-loader": "^2.5.5",
+ "@hono/node-server": "^1.9.0",
+ "@hono/zod-validator": "^0.2.0",
+ "camelcase": "^7.0.1",
+ "chalk": "^5.2.0",
+ "commander": "^9.4.1",
+ "env-paths": "^3.0.0",
+ "esbuild": "^0.19.7",
+ "esbuild-register": "^3.5.0",
+ "glob": "^8.1.0",
+ "hanji": "^0.0.5",
+ "hono": "^4.1.4",
+ "json-diff": "0.9.0",
+ "minimatch": "^7.4.3",
+ "semver": "^7.5.4",
+ "superjson": "^2.2.1",
+ "zod": "^3.20.2"
+ },
+ "bin": {
+ "drizzle-kit": "bin.cjs"
+ }
+ },
+ "node_modules/drizzle-kit/node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/drizzle-orm": {
+ "version": "0.45.2",
+ "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.45.2.tgz",
+ "integrity": "sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@aws-sdk/client-rds-data": ">=3",
+ "@cloudflare/workers-types": ">=4",
+ "@electric-sql/pglite": ">=0.2.0",
+ "@libsql/client": ">=0.10.0",
+ "@libsql/client-wasm": ">=0.10.0",
+ "@neondatabase/serverless": ">=0.10.0",
+ "@op-engineering/op-sqlite": ">=2",
+ "@opentelemetry/api": "^1.4.1",
+ "@planetscale/database": ">=1.13",
+ "@prisma/client": "*",
+ "@tidbcloud/serverless": "*",
+ "@types/better-sqlite3": "*",
+ "@types/pg": "*",
+ "@types/sql.js": "*",
+ "@upstash/redis": ">=1.34.7",
+ "@vercel/postgres": ">=0.8.0",
+ "@xata.io/client": "*",
+ "better-sqlite3": ">=7",
+ "bun-types": "*",
+ "expo-sqlite": ">=14.0.0",
+ "gel": ">=2",
+ "knex": "*",
+ "kysely": "*",
+ "mysql2": ">=2",
+ "pg": ">=8",
+ "postgres": ">=3",
+ "sql.js": ">=1",
+ "sqlite3": ">=5"
+ },
+ "peerDependenciesMeta": {
+ "@aws-sdk/client-rds-data": {
+ "optional": true
+ },
+ "@cloudflare/workers-types": {
+ "optional": true
+ },
+ "@electric-sql/pglite": {
+ "optional": true
+ },
+ "@libsql/client": {
+ "optional": true
+ },
+ "@libsql/client-wasm": {
+ "optional": true
+ },
+ "@neondatabase/serverless": {
+ "optional": true
+ },
+ "@op-engineering/op-sqlite": {
+ "optional": true
+ },
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@planetscale/database": {
+ "optional": true
+ },
+ "@prisma/client": {
+ "optional": true
+ },
+ "@tidbcloud/serverless": {
+ "optional": true
+ },
+ "@types/better-sqlite3": {
+ "optional": true
+ },
+ "@types/pg": {
+ "optional": true
+ },
+ "@types/sql.js": {
+ "optional": true
+ },
+ "@upstash/redis": {
+ "optional": true
+ },
+ "@vercel/postgres": {
+ "optional": true
+ },
+ "@xata.io/client": {
+ "optional": true
+ },
+ "better-sqlite3": {
+ "optional": true
+ },
+ "bun-types": {
+ "optional": true
+ },
+ "expo-sqlite": {
+ "optional": true
+ },
+ "gel": {
+ "optional": true
+ },
+ "knex": {
+ "optional": true
+ },
+ "kysely": {
+ "optional": true
+ },
+ "mysql2": {
+ "optional": true
+ },
+ "pg": {
+ "optional": true
+ },
+ "postgres": {
+ "optional": true
+ },
+ "prisma": {
+ "optional": true
+ },
+ "sql.js": {
+ "optional": true
+ },
+ "sqlite3": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
+ "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz",
+ "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es5-ext": {
+ "version": "0.10.64",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
+ "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "ISC",
+ "dependencies": {
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.3",
+ "esniff": "^2.0.1",
+ "next-tick": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "node_modules/es6-symbol": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
+ "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "d": "^1.0.2",
+ "ext": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/es6-weak-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
+ "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "^0.10.46",
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.19.12",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
+ "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.19.12",
+ "@esbuild/android-arm": "0.19.12",
+ "@esbuild/android-arm64": "0.19.12",
+ "@esbuild/android-x64": "0.19.12",
+ "@esbuild/darwin-arm64": "0.19.12",
+ "@esbuild/darwin-x64": "0.19.12",
+ "@esbuild/freebsd-arm64": "0.19.12",
+ "@esbuild/freebsd-x64": "0.19.12",
+ "@esbuild/linux-arm": "0.19.12",
+ "@esbuild/linux-arm64": "0.19.12",
+ "@esbuild/linux-ia32": "0.19.12",
+ "@esbuild/linux-loong64": "0.19.12",
+ "@esbuild/linux-mips64el": "0.19.12",
+ "@esbuild/linux-ppc64": "0.19.12",
+ "@esbuild/linux-riscv64": "0.19.12",
+ "@esbuild/linux-s390x": "0.19.12",
+ "@esbuild/linux-x64": "0.19.12",
+ "@esbuild/netbsd-x64": "0.19.12",
+ "@esbuild/openbsd-x64": "0.19.12",
+ "@esbuild/sunos-x64": "0.19.12",
+ "@esbuild/win32-arm64": "0.19.12",
+ "@esbuild/win32-ia32": "0.19.12",
+ "@esbuild/win32-x64": "0.19.12"
+ }
+ },
+ "node_modules/esbuild-register": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz",
+ "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "peerDependencies": {
+ "esbuild": ">=0.12 <1"
+ }
+ },
+ "node_modules/esniff": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
+ "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "d": "^1.0.1",
+ "es5-ext": "^0.10.62",
+ "event-emitter": "^0.3.5",
+ "type": "^2.7.2"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "license": "(MIT OR WTFPL)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/expect-type": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz",
+ "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/ext": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
+ "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "type": "^2.7.2"
+ }
+ },
+ "node_modules/fast-decode-uri-component": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz",
+ "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==",
+ "license": "MIT"
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stringify": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-7.0.1.tgz",
+ "integrity": "sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/merge-json-schemas": "^0.2.0",
+ "ajv": "^8.12.0",
+ "ajv-formats": "^3.0.1",
+ "fast-uri": "^4.0.0",
+ "json-schema-ref-resolver": "^3.0.0",
+ "rfdc": "^1.2.0"
+ }
+ },
+ "node_modules/fast-jwt": {
+ "version": "6.3.2",
+ "resolved": "https://registry.npmjs.org/fast-jwt/-/fast-jwt-6.3.2.tgz",
+ "integrity": "sha512-JTQImpkXVvj+eq7tJImtsHRt1K6ngloEzIx62Qbf9x4tEM2P2EqGpYJSeUoPf/kMn78rImSHfhf08KShR8PauA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@lukeed/ms": "^2.0.2",
+ "asn1.js": "^5.4.1",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "mnemonist": "^0.40.0",
+ "safe-regex2": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/fast-jwt/node_modules/mnemonist": {
+ "version": "0.40.4",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.40.4.tgz",
+ "integrity": "sha512-ZAv+KNavneRVzu4tUeOgzkScI3W5BGwZ3rkxIpKtzzVgfTtWQFN1CgX0U72cyvyh3iTuHL3SiSmrQxTlryEIcw==",
+ "license": "MIT",
+ "dependencies": {
+ "obliterator": "^2.0.4"
+ }
+ },
+ "node_modules/fast-querystring": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz",
+ "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-decode-uri-component": "^1.0.1"
+ }
+ },
+ "node_modules/fast-uri": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-4.1.2.tgz",
+ "integrity": "sha512-TyGmBcbDTZXcb2cj5MV89DrF42DKvb3y5DDUNh95iO+IMeAzMkVSxK1PZRrRIpc9yg8U2GhGdbofNa0LS/a4Bw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fastfall": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz",
+ "integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "reusify": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fastify": {
+ "version": "5.11.3",
+ "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.11.3.tgz",
+ "integrity": "sha512-W6hzDP8s0iSeL7LGwY6Oc/ZxuXWOvFEMs6p2L0Si415YRo27W5pBKdOTXxhemBDeSTAcpYf5evRA9onF2OYhPA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/ajv-compiler": "^4.0.5",
+ "@fastify/error": "^4.0.0",
+ "@fastify/fast-json-stringify-compiler": "^5.0.0",
+ "@fastify/proxy-addr": "^5.0.0",
+ "abstract-logging": "^2.0.1",
+ "avvio": "^9.0.0",
+ "fast-json-stringify": "^7.0.0",
+ "find-my-way": "^9.6.0",
+ "light-my-request": "^6.0.0",
+ "pino": "^9.14.0 || ^10.1.0",
+ "process-warning": "^5.0.0",
+ "rfdc": "^1.3.1",
+ "secure-json-parse": "^4.0.0",
+ "semver": "^7.6.0",
+ "toad-cache": "^3.7.0"
+ }
+ },
+ "node_modules/fastify-plugin": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.1.0.tgz",
+ "integrity": "sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/fastparallel": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz",
+ "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4",
+ "xtend": "^4.0.2"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fastseries": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz",
+ "integrity": "sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "license": "MIT"
+ },
+ "node_modules/find-my-way": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.7.0.tgz",
+ "integrity": "sha512-f2JHn75x2JlwUwLenZypgczR7YWMb/uO9BvUXtus+JMgkbIkLADd38cI4EiV+OQqrGo1Zlq6V8wnqMJ8e62wUQ==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-querystring": "^1.0.0",
+ "safe-regex2": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "license": "MIT",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.14.1",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.1.tgz",
+ "integrity": "sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "license": "MIT"
+ },
+ "node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "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",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/hanji": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/hanji/-/hanji-0.0.5.tgz",
+ "integrity": "sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "lodash.throttle": "^4.1.1",
+ "sisteransi": "^1.0.5"
+ }
+ },
+ "node_modules/heap": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
+ "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hono": {
+ "version": "4.13.1",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz",
+ "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.9.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/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.",
+ "dev": true,
+ "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/ipaddr.js": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.5.0.tgz",
+ "integrity": "sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
+ "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-what": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz",
+ "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/json-diff": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.9.0.tgz",
+ "integrity": "sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cli-color": "^2.0.0",
+ "difflib": "~0.2.1",
+ "dreamopt": "~0.8.0"
+ },
+ "bin": {
+ "json-diff": "bin/json-diff.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/json-schema-ref-resolver": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-3.0.0.tgz",
+ "integrity": "sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/light-my-request": {
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz",
+ "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "process-warning": "^4.0.0",
+ "set-cookie-parser": "^2.6.0"
+ }
+ },
+ "node_modules/light-my-request/node_modules/process-warning": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz",
+ "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "dev": true,
+ "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.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "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.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
+ "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es5-ext": "~0.10.2"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/memoizee": {
+ "version": "0.4.17",
+ "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz",
+ "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "d": "^1.0.2",
+ "es5-ext": "^0.10.64",
+ "es6-weak-map": "^2.0.3",
+ "event-emitter": "^0.3.5",
+ "is-promise": "^2.2.2",
+ "lru-queue": "^0.1.0",
+ "next-tick": "^1.1.0",
+ "timers-ext": "^0.1.7"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "license": "ISC"
+ },
+ "node_modules/minimatch": {
+ "version": "7.4.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.9.tgz",
+ "integrity": "sha512-Brg/fp/iAVDOQoHxkuN5bEYhyQlZhxddI78yWsCbeEwTHXQjlNLtiJDUsp1GIptVqMI7/gkJMz4vVAc01mpoBw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "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/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "license": "MIT"
+ },
+ "node_modules/mnemonist": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.40.0.tgz",
+ "integrity": "sha512-kdd8AFNig2AD5Rkih7EPCXhu/iMvwevQFX/uEiGhZyPZi7fHqOoF4V4kHLpCfysxXMgQ4B52kdPMCwARshKvEg==",
+ "license": "MIT",
+ "dependencies": {
+ "obliterator": "^2.0.4"
+ }
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "5.1.16",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.16.tgz",
+ "integrity": "sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.js"
+ },
+ "engines": {
+ "node": "^18 || >=20"
+ }
+ },
+ "node_modules/napi-build-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
+ "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
+ "license": "MIT"
+ },
+ "node_modules/next-tick": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
+ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/node-abi": {
+ "version": "3.94.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz",
+ "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "license": "MIT",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/obliterator": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz",
+ "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==",
+ "license": "MIT"
+ },
+ "node_modules/obug": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz",
+ "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/on-exit-leak-free": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
+ "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "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/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pino": {
+ "version": "9.14.0",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz",
+ "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==",
+ "license": "MIT",
+ "dependencies": {
+ "@pinojs/redact": "^0.4.0",
+ "atomic-sleep": "^1.0.0",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "^2.0.0",
+ "pino-std-serializers": "^7.0.0",
+ "process-warning": "^5.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "sonic-boom": "^4.0.1",
+ "thread-stream": "^3.0.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
+ "node_modules/pino-abstract-transport": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
+ "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
+ "license": "MIT",
+ "dependencies": {
+ "split2": "^4.0.0"
+ }
+ },
+ "node_modules/pino-std-serializers": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz",
+ "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==",
+ "license": "MIT"
+ },
+ "node_modules/postcss": {
+ "version": "8.5.26",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
+ "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
+ "dev": true,
+ "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.17",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss/node_modules/nanoid": {
+ "version": "3.3.18",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
+ "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
+ "dev": true,
+ "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/prebuild-install": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
+ "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
+ "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^2.0.0",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/process-warning": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.1.0.tgz",
+ "integrity": "sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/pump": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
+ "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/quick-format-unescaped": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
+ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
+ "license": "MIT"
+ },
+ "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/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/real-require": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
+ "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12.13.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/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
+ "node_modules/ret": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz",
+ "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "license": "MIT"
+ },
+ "node_modules/rolldown": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz",
+ "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.143.0",
+ "@rolldown/pluginutils": "^1.0.0"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.2.3",
+ "@rolldown/binding-darwin-arm64": "1.2.3",
+ "@rolldown/binding-darwin-x64": "1.2.3",
+ "@rolldown/binding-freebsd-x64": "1.2.3",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.3",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.3",
+ "@rolldown/binding-linux-arm64-musl": "1.2.3",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.3",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.3",
+ "@rolldown/binding-linux-x64-gnu": "1.2.3",
+ "@rolldown/binding-linux-x64-musl": "1.2.3",
+ "@rolldown/binding-openharmony-arm64": "1.2.3",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.3",
+ "@rolldown/binding-win32-x64-msvc": "1.2.3"
+ }
+ },
+ "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/safe-regex2": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.1.1.tgz",
+ "integrity": "sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "ret": "~0.5.0"
+ },
+ "bin": {
+ "safe-regex2": "bin/safe-regex2.js"
+ }
+ },
+ "node_modules/safe-stable-stringify": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
+ "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/secure-json-parse": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz",
+ "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/semver": {
+ "version": "7.8.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
+ "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
+ "node_modules/siginfo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/sonic-boom": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz",
+ "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/stackback": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/std-env": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
+ "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/steed": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/steed/-/steed-1.1.3.tgz",
+ "integrity": "sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==",
+ "license": "MIT",
+ "dependencies": {
+ "fastfall": "^1.5.0",
+ "fastparallel": "^2.2.0",
+ "fastq": "^1.3.0",
+ "fastseries": "^1.7.0",
+ "reusify": "^1.0.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/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/superjson": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
+ "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "copy-anything": "^4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
+ "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/thread-stream": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz",
+ "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==",
+ "license": "MIT",
+ "dependencies": {
+ "real-require": "^0.2.0"
+ }
+ },
+ "node_modules/timers-ext": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz",
+ "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "es5-ext": "^0.10.64",
+ "next-tick": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/tinybench": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyexec": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz",
+ "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz",
+ "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/toad-cache": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.4.tgz",
+ "integrity": "sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/tsx": {
+ "version": "4.23.12",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz",
+ "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.28.0"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/esbuild": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.2",
+ "@esbuild/android-arm": "0.28.2",
+ "@esbuild/android-arm64": "0.28.2",
+ "@esbuild/android-x64": "0.28.2",
+ "@esbuild/darwin-arm64": "0.28.2",
+ "@esbuild/darwin-x64": "0.28.2",
+ "@esbuild/freebsd-arm64": "0.28.2",
+ "@esbuild/freebsd-x64": "0.28.2",
+ "@esbuild/linux-arm": "0.28.2",
+ "@esbuild/linux-arm64": "0.28.2",
+ "@esbuild/linux-ia32": "0.28.2",
+ "@esbuild/linux-loong64": "0.28.2",
+ "@esbuild/linux-mips64el": "0.28.2",
+ "@esbuild/linux-ppc64": "0.28.2",
+ "@esbuild/linux-riscv64": "0.28.2",
+ "@esbuild/linux-s390x": "0.28.2",
+ "@esbuild/linux-x64": "0.28.2",
+ "@esbuild/netbsd-arm64": "0.28.2",
+ "@esbuild/netbsd-x64": "0.28.2",
+ "@esbuild/openbsd-arm64": "0.28.2",
+ "@esbuild/openbsd-x64": "0.28.2",
+ "@esbuild/openharmony-arm64": "0.28.2",
+ "@esbuild/sunos-x64": "0.28.2",
+ "@esbuild/win32-arm64": "0.28.2",
+ "@esbuild/win32-ia32": "0.28.2",
+ "@esbuild/win32-x64": "0.28.2"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/type": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
+ "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "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-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/vitest": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz",
+ "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/expect": "4.1.10",
+ "@vitest/mocker": "4.1.10",
+ "@vitest/pretty-format": "4.1.10",
+ "@vitest/runner": "4.1.10",
+ "@vitest/snapshot": "4.1.10",
+ "@vitest/spy": "4.1.10",
+ "@vitest/utils": "4.1.10",
+ "es-module-lexer": "^2.0.0",
+ "expect-type": "^1.3.0",
+ "magic-string": "^0.30.21",
+ "obug": "^2.1.1",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.3",
+ "std-env": "^4.0.0-rc.1",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^1.0.2",
+ "tinyglobby": "^0.2.15",
+ "tinyrainbow": "^3.1.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "4.1.10",
+ "@vitest/browser-preview": "4.1.10",
+ "@vitest/browser-webdriverio": "4.1.10",
+ "@vitest/coverage-istanbul": "4.1.10",
+ "@vitest/coverage-v8": "4.1.10",
+ "@vitest/ui": "4.1.10",
+ "happy-dom": "*",
+ "jsdom": "*",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ },
+ "vite": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/android-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/android-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/android-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/linux-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@esbuild/win32-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/vitest/node_modules/@vitest/mocker": {
+ "version": "4.1.10",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz",
+ "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/spy": "4.1.10",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.21"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitest/node_modules/esbuild": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.2",
+ "@esbuild/android-arm": "0.28.2",
+ "@esbuild/android-arm64": "0.28.2",
+ "@esbuild/android-x64": "0.28.2",
+ "@esbuild/darwin-arm64": "0.28.2",
+ "@esbuild/darwin-x64": "0.28.2",
+ "@esbuild/freebsd-arm64": "0.28.2",
+ "@esbuild/freebsd-x64": "0.28.2",
+ "@esbuild/linux-arm": "0.28.2",
+ "@esbuild/linux-arm64": "0.28.2",
+ "@esbuild/linux-ia32": "0.28.2",
+ "@esbuild/linux-loong64": "0.28.2",
+ "@esbuild/linux-mips64el": "0.28.2",
+ "@esbuild/linux-ppc64": "0.28.2",
+ "@esbuild/linux-riscv64": "0.28.2",
+ "@esbuild/linux-s390x": "0.28.2",
+ "@esbuild/linux-x64": "0.28.2",
+ "@esbuild/netbsd-arm64": "0.28.2",
+ "@esbuild/netbsd-x64": "0.28.2",
+ "@esbuild/openbsd-arm64": "0.28.2",
+ "@esbuild/openbsd-x64": "0.28.2",
+ "@esbuild/openharmony-arm64": "0.28.2",
+ "@esbuild/sunos-x64": "0.28.2",
+ "@esbuild/win32-arm64": "0.28.2",
+ "@esbuild/win32-ia32": "0.28.2",
+ "@esbuild/win32-x64": "0.28.2"
+ }
+ },
+ "node_modules/vitest/node_modules/vite": {
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz",
+ "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.33.0",
+ "picomatch": "^4.0.5",
+ "postcss": "^8.5.25",
+ "rolldown": "~1.2.1",
+ "tinyglobby": "^0.2.17"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.4.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/why-is-node-running": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "siginfo": "^2.0.0",
+ "stackback": "0.0.2"
+ },
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true,
+ "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/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "packages/api": {
+ "name": "@evodron/api",
+ "version": "0.1.0",
+ "dependencies": {
+ "@evodron/db": "*",
+ "@evodron/shared": "*",
+ "@fastify/cors": "^10.1.0",
+ "@fastify/jwt": "^10.2.1",
+ "@fastify/rate-limit": "^10.3.0",
+ "bcryptjs": "^2.4.3",
+ "dotenv": "^16.4.5",
+ "drizzle-orm": "^0.45.2",
+ "fastify": "^5.9.0",
+ "nanoid": "^5.0.4",
+ "zod": "^3.22.4"
+ },
+ "devDependencies": {
+ "@types/bcryptjs": "^2.4.6",
+ "@types/node": "^20.11.25",
+ "tsx": "^4.7.1",
+ "typescript": "^5.3.3",
+ "vitest": "^4.1.10"
+ }
+ },
+ "packages/cli": {
+ "name": "@evodron/cli",
+ "version": "0.1.0",
+ "dependencies": {
+ "@evodron/shared": "*",
+ "chalk": "^5.3.0",
+ "commander": "^12.0.0",
+ "dotenv": "^16.4.5",
+ "node-fetch": "^3.3.2"
+ },
+ "bin": {
+ "evodron": "dist/bin/evodron.js"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.25",
+ "tsx": "^4.7.1",
+ "typescript": "^5.3.3",
+ "vitest": "^4.1.10"
+ }
+ },
+ "packages/db": {
+ "name": "@evodron/db",
+ "version": "0.1.0",
+ "dependencies": {
+ "better-sqlite3": "^9.4.3",
+ "drizzle-orm": "^0.45.2",
+ "nanoid": "^5.0.4"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "^7.6.8",
+ "drizzle-kit": "^0.20.14",
+ "tsx": "^4.7.1",
+ "typescript": "^5.3.3"
+ }
+ },
+ "packages/shared": {
+ "name": "@evodron/shared",
+ "version": "0.1.0",
+ "dependencies": {
+ "zod": "^3.22.4"
+ },
+ "devDependencies": {
+ "typescript": "^5.3.3"
+ }
+ }
+ }
+}
diff --git a/evodron/package.json b/evodron/package.json
new file mode 100644
index 00000000..073e936c
--- /dev/null
+++ b/evodron/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "evodron",
+ "version": "0.1.0",
+ "description": "EVODRON — AI-powered developer platform built around the GitHub Copilot CLI",
+ "private": true,
+ "workspaces": [
+ "packages/*"
+ ],
+ "scripts": {
+ "build": "npm run build --workspaces",
+ "test": "npm run test --workspaces --if-present",
+ "lint": "npm run lint --workspaces --if-present",
+ "dev:api": "npm run dev --workspace=packages/api",
+ "dev:cli": "npm run dev --workspace=packages/cli",
+ "db:migrate": "npm run migrate --workspace=packages/db",
+ "db:seed": "npm run seed --workspace=packages/db"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "keywords": [
+ "evodron",
+ "ai",
+ "cli",
+ "developer-tools"
+ ],
+ "author": "EVODRON",
+ "license": "UNLICENSED"
+}
diff --git a/evodron/packages/api/:memory:?cache=shared b/evodron/packages/api/:memory:?cache=shared
new file mode 100644
index 0000000000000000000000000000000000000000..2f7292d0901b002071ec05a1b6f78ffec474647f
GIT binary patch
literal 4096
zcmWFz^vNtqRY=P(%1ta$FlG>7U}9o$P*7lCU|@t|AVoG{WY8<^^dNAlr;ljiVtj
n8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O6ovo*c9sVc
literal 0
HcmV?d00001
diff --git a/evodron/packages/api/:memory:?cache=shared-shm b/evodron/packages/api/:memory:?cache=shared-shm
new file mode 100644
index 0000000000000000000000000000000000000000..fe9ac2845eca6fe6da8a63cd096d9cf9e24ece10
GIT binary patch
literal 32768
zcmeIuAr62r3 {
+ // Run migrations on the same file that getDb() will use
+ const Database = (await import('better-sqlite3')).default;
+ const db = new Database(testDbPath);
+ db.pragma('journal_mode = WAL');
+ db.pragma('foreign_keys = ON');
+
+ const migrations = [
+ `CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, email TEXT NOT NULL UNIQUE, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, referral_code TEXT NOT NULL UNIQUE, referred_by TEXT, credits INTEGER NOT NULL DEFAULT 0, level TEXT NOT NULL DEFAULT 'bronze', is_admin INTEGER NOT NULL DEFAULT 0, is_banned INTEGER NOT NULL DEFAULT 0, consent_metrics INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL)`,
+ `CREATE TABLE IF NOT EXISTS sessions (id TEXT PRIMARY KEY, user_id TEXT NOT NULL, started_at TEXT NOT NULL, ended_at TEXT, commands_count INTEGER NOT NULL DEFAULT 0, client_version TEXT, ip_hash TEXT)`,
+ `CREATE TABLE IF NOT EXISTS referrals (id TEXT PRIMARY KEY, referrer_id TEXT NOT NULL, referee_id TEXT NOT NULL UNIQUE, status TEXT NOT NULL DEFAULT 'pending', activated_at TEXT, rewarded_at TEXT, created_at TEXT NOT NULL)`,
+ `CREATE TABLE IF NOT EXISTS rewards (id TEXT PRIMARY KEY, user_id TEXT NOT NULL, type TEXT NOT NULL, amount INTEGER NOT NULL, source TEXT NOT NULL, created_at TEXT NOT NULL)`,
+ `CREATE TABLE IF NOT EXISTS reward_rules (id TEXT PRIMARY KEY, name TEXT NOT NULL UNIQUE, trigger TEXT NOT NULL, credits INTEGER NOT NULL, active INTEGER NOT NULL DEFAULT 1, description TEXT, updated_at TEXT NOT NULL)`,
+ `CREATE TABLE IF NOT EXISTS abuse_flags (id TEXT PRIMARY KEY, user_id TEXT NOT NULL, reason TEXT NOT NULL, detail TEXT, resolved_at TEXT, flagged_at TEXT NOT NULL)`,
+ `CREATE TABLE IF NOT EXISTS ip_registry (id TEXT PRIMARY KEY, ip_hash TEXT NOT NULL, user_id TEXT NOT NULL, seen_at TEXT NOT NULL)`,
+ `CREATE TABLE IF NOT EXISTS refresh_tokens (id TEXT PRIMARY KEY, user_id TEXT NOT NULL, token_hash TEXT NOT NULL UNIQUE, expires_at TEXT NOT NULL, created_at TEXT NOT NULL, revoked_at TEXT)`,
+ ];
+
+ db.transaction(() => {
+ for (const sql of migrations) db.prepare(sql).run();
+ })();
+ db.close();
+
+ app = await buildApp();
+ await app.ready();
+});
+
+afterAll(async () => {
+ await app?.close();
+ // Clean up test DB file
+ try { fs.unlinkSync(testDbPath); } catch { /* ignore */ }
+ try { fs.unlinkSync(testDbPath + '-wal'); } catch { /* ignore */ }
+ try { fs.unlinkSync(testDbPath + '-shm'); } catch { /* ignore */ }
+});
+
+describe('Health check', () => {
+ it('GET /health returns ok', async () => {
+ const res = await app.inject({ method: 'GET', url: '/health' });
+ expect(res.statusCode).toBe(200);
+ const body = res.json();
+ expect(body.status).toBe('ok');
+ expect(body.service).toBe('evodron-api');
+ });
+});
+
+describe('Auth — register and login', () => {
+ const email = `test-${Date.now()}@example.com`;
+ const username = `user${Date.now()}`;
+ const password = 'StrongPass123!';
+
+ it('POST /auth/register creates a user', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: { email, username, password },
+ });
+ expect(res.statusCode).toBe(201);
+ const body = res.json();
+ expect(body.success).toBe(true);
+ expect(body.data.accessToken).toBeDefined();
+ expect(body.data.refreshToken).toBeDefined();
+ });
+
+ it('POST /auth/register rejects duplicate email', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: { email, username: username + '2', password },
+ });
+ expect(res.statusCode).toBe(409);
+ });
+
+ it('POST /auth/login with valid credentials returns tokens', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/auth/login',
+ payload: { email, password },
+ });
+ expect(res.statusCode).toBe(200);
+ const body = res.json();
+ expect(body.success).toBe(true);
+ expect(body.data.accessToken).toBeDefined();
+ });
+
+ it('POST /auth/login with wrong password returns 401', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/auth/login',
+ payload: { email, password: 'wrongpassword' },
+ });
+ expect(res.statusCode).toBe(401);
+ });
+});
+
+describe('Users — /users/me', () => {
+ let accessToken: string;
+
+ beforeAll(async () => {
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `me-${Date.now()}@example.com`,
+ username: `meuser${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+ accessToken = reg.json().data.accessToken;
+ });
+
+ it('GET /users/me returns profile', async () => {
+ const res = await app.inject({
+ method: 'GET',
+ url: '/users/me',
+ headers: { authorization: 'Bearer ' + accessToken },
+ });
+ expect(res.statusCode).toBe(200);
+ const body = res.json();
+ expect(body.success).toBe(true);
+ expect(body.data.referralCode).toBeDefined();
+ expect(body.data.referralLink).toContain('/ref/');
+ });
+
+ it('GET /users/me without token returns 401', async () => {
+ const res = await app.inject({ method: 'GET', url: '/users/me' });
+ expect(res.statusCode).toBe(401);
+ });
+});
+
+describe('Referral system', () => {
+ let referrerToken: string;
+ let referralCode: string;
+
+ beforeAll(async () => {
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `referrer-${Date.now()}@example.com`,
+ username: `referrer${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+ const data = reg.json().data;
+ referrerToken = data.accessToken;
+ referralCode = data.referralCode;
+ });
+
+ it('GET /referrals/code returns code and link', async () => {
+ const res = await app.inject({
+ method: 'GET',
+ url: '/referrals/code',
+ headers: { authorization: 'Bearer ' + referrerToken },
+ });
+ expect(res.statusCode).toBe(200);
+ const body = res.json();
+ expect(body.data.code).toHaveLength(8);
+ expect(body.data.link).toContain('/ref/');
+ });
+
+ it('Registering with valid referral code creates pending referral', async () => {
+ const regRes = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `referee-${Date.now()}@example.com`,
+ username: `referee${Date.now()}`,
+ password: 'StrongPass123!',
+ referralCode,
+ },
+ });
+ expect(regRes.statusCode).toBe(201);
+
+ // Check referral stats
+ const statsRes = await app.inject({
+ method: 'GET',
+ url: '/referrals/stats',
+ headers: { authorization: 'Bearer ' + referrerToken },
+ });
+ const stats = statsRes.json().data;
+ expect(stats.totalReferrals).toBeGreaterThanOrEqual(1);
+ expect(stats.pendingReferrals).toBeGreaterThanOrEqual(1);
+ });
+
+ it('Registering with invalid referral code returns 400', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `badref-${Date.now()}@example.com`,
+ username: `badref${Date.now()}`,
+ password: 'StrongPass123!',
+ referralCode: 'INVALID1',
+ },
+ });
+ expect(res.statusCode).toBe(400);
+ expect(res.json().code).toBe('INVALID_REFERRAL');
+ });
+});
+
+describe('Sessions', () => {
+ let token: string;
+ let sessionId: string;
+
+ beforeAll(async () => {
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `session-${Date.now()}@example.com`,
+ username: `sessionuser${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+ token = reg.json().data.accessToken;
+ });
+
+ it('POST /sessions/start returns sessionId', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/sessions/start',
+ headers: { authorization: 'Bearer ' + token },
+ payload: { clientVersion: '0.1.0' },
+ });
+ expect(res.statusCode).toBe(201);
+ sessionId = res.json().data.sessionId;
+ expect(sessionId).toBeDefined();
+ });
+
+ it('POST /sessions/end completes session', async () => {
+ const res = await app.inject({
+ method: 'POST',
+ url: '/sessions/end',
+ headers: { authorization: 'Bearer ' + token },
+ payload: { sessionId, commandsCount: 5 },
+ });
+ expect(res.statusCode).toBe(200);
+ });
+});
+
+describe('Rewards', () => {
+ let token: string;
+
+ beforeAll(async () => {
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `rewards-${Date.now()}@example.com`,
+ username: `rewarduser${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+ token = reg.json().data.accessToken;
+ });
+
+ it('GET /rewards returns reward history', async () => {
+ const res = await app.inject({
+ method: 'GET',
+ url: '/rewards',
+ headers: { authorization: 'Bearer ' + token },
+ });
+ expect(res.statusCode).toBe(200);
+ const body = res.json();
+ expect(body.success).toBe(true);
+ expect(Array.isArray(body.data.rewards)).toBe(true);
+ });
+});
+
+describe('Stats', () => {
+ let token: string;
+
+ beforeAll(async () => {
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `stats-${Date.now()}@example.com`,
+ username: `statsuser${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+ token = reg.json().data.accessToken;
+ });
+
+ it('GET /stats returns usage stats', async () => {
+ const res = await app.inject({
+ method: 'GET',
+ url: '/stats',
+ headers: { authorization: 'Bearer ' + token },
+ });
+ expect(res.statusCode).toBe(200);
+ const body = res.json();
+ expect(body.data.level).toBe('bronze');
+ expect(body.data.totalSessions).toBe(0);
+ });
+});
diff --git a/evodron/packages/api/src/__tests__/unit/helpers.test.ts b/evodron/packages/api/src/__tests__/unit/helpers.test.ts
new file mode 100644
index 00000000..26d1361c
--- /dev/null
+++ b/evodron/packages/api/src/__tests__/unit/helpers.test.ts
@@ -0,0 +1,60 @@
+import { describe, it, expect } from 'vitest';
+import { hashIp, randomCode, uuid, now } from '../../middleware/helpers';
+
+describe('helpers', () => {
+ describe('hashIp', () => {
+ it('returns a 64-char hex string', () => {
+ const hash = hashIp('192.168.1.1');
+ expect(hash).toHaveLength(64);
+ expect(/^[0-9a-f]+$/.test(hash)).toBe(true);
+ });
+
+ it('is deterministic for the same input', () => {
+ expect(hashIp('10.0.0.1')).toBe(hashIp('10.0.0.1'));
+ });
+
+ it('produces different hashes for different IPs', () => {
+ expect(hashIp('1.1.1.1')).not.toBe(hashIp('2.2.2.2'));
+ });
+ });
+
+ describe('randomCode', () => {
+ it('generates a code of the default length (8)', () => {
+ expect(randomCode()).toHaveLength(8);
+ });
+
+ it('generates a code of a custom length', () => {
+ expect(randomCode(12)).toHaveLength(12);
+ });
+
+ it('generates different codes on each call', () => {
+ const codes = new Set(Array.from({ length: 20 }, () => randomCode()));
+ expect(codes.size).toBeGreaterThan(15);
+ });
+
+ it('only contains safe alphanumeric characters', () => {
+ const code = randomCode(100);
+ expect(/^[A-Za-z0-9]+$/.test(code)).toBe(true);
+ });
+ });
+
+ describe('uuid', () => {
+ it('returns a valid UUID v4 format', () => {
+ const id = uuid();
+ expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
+ });
+
+ it('generates unique values', () => {
+ const ids = new Set(Array.from({ length: 50 }, () => uuid()));
+ expect(ids.size).toBe(50);
+ });
+ });
+
+ describe('now', () => {
+ it('returns a valid ISO 8601 string', () => {
+ const ts = now();
+ expect(() => new Date(ts).toISOString()).not.toThrow();
+ expect(ts).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
+ });
+ });
+});
diff --git a/evodron/packages/api/src/index.ts b/evodron/packages/api/src/index.ts
new file mode 100644
index 00000000..a2dce2bb
--- /dev/null
+++ b/evodron/packages/api/src/index.ts
@@ -0,0 +1,85 @@
+import 'dotenv/config';
+import Fastify from 'fastify';
+import cors from '@fastify/cors';
+import jwt from '@fastify/jwt';
+import rateLimit from '@fastify/rate-limit';
+
+import { authRoutes } from './routes/auth';
+import { userRoutes } from './routes/users';
+import { sessionRoutes } from './routes/sessions';
+import { referralRoutes } from './routes/referrals';
+import { rewardRoutes } from './routes/rewards';
+import { statsRoutes } from './routes/stats';
+import { adminRoutes } from './routes/admin';
+import { getDb } from '@evodron/db';
+
+const PORT = parseInt(process.env['EVODRON_API_PORT'] ?? '3000', 10);
+const HOST = process.env['EVODRON_API_HOST'] ?? '0.0.0.0';
+
+export async function buildApp() {
+ const app = Fastify({
+ logger: {
+ level: process.env['LOG_LEVEL'] ?? 'info',
+ },
+ trustProxy: true,
+ });
+
+ // ── Plugins ──────────────────────────────────────────────────────────────
+
+ await app.register(cors, {
+ origin: true,
+ credentials: true,
+ });
+
+ await app.register(rateLimit, {
+ max: 100,
+ timeWindow: '1 minute',
+ errorResponseBuilder: () => ({
+ success: false,
+ error: 'Too many requests. Please slow down.',
+ code: 'RATE_LIMITED',
+ }),
+ });
+
+ const jwtSecret = process.env['EVODRON_JWT_SECRET'];
+ if (!jwtSecret || jwtSecret === 'change-me-to-a-long-random-secret') {
+ throw new Error('EVODRON_JWT_SECRET must be set to a secure value');
+ }
+
+ await app.register(jwt, {
+ secret: jwtSecret,
+ sign: { expiresIn: '15m' },
+ });
+
+ // ── Database ─────────────────────────────────────────────────────────────
+
+ const db = getDb();
+ app.decorate('db', db);
+
+ // ── Routes ───────────────────────────────────────────────────────────────
+
+ await app.register(authRoutes, { prefix: '/auth' });
+ await app.register(userRoutes, { prefix: '/users' });
+ await app.register(sessionRoutes, { prefix: '/sessions' });
+ await app.register(referralRoutes, { prefix: '/referrals' });
+ await app.register(rewardRoutes, { prefix: '/rewards' });
+ await app.register(statsRoutes, { prefix: '/stats' });
+ await app.register(adminRoutes, { prefix: '/admin' });
+
+ // ── Health check ─────────────────────────────────────────────────────────
+
+ app.get('/health', async () => ({ status: 'ok', service: 'evodron-api' }));
+
+ return app;
+}
+
+// Start when run directly
+if (require.main === module) {
+ buildApp()
+ .then((app) => app.listen({ port: PORT, host: HOST }))
+ .then(() => console.log(`EVODRON API listening on ${HOST}:${PORT}`))
+ .catch((err) => {
+ console.error(err);
+ process.exit(1);
+ });
+}
diff --git a/evodron/packages/api/src/middleware/auth.ts b/evodron/packages/api/src/middleware/auth.ts
new file mode 100644
index 00000000..9bc35b7d
--- /dev/null
+++ b/evodron/packages/api/src/middleware/auth.ts
@@ -0,0 +1,27 @@
+import { FastifyReply, FastifyRequest } from 'fastify';
+
+export async function authenticate(
+ request: FastifyRequest,
+ reply: FastifyReply,
+): Promise {
+ try {
+ await request.jwtVerify();
+ } catch {
+ reply.code(401).send({ success: false, error: 'Unauthorized', code: 'UNAUTHORIZED' });
+ }
+}
+
+export async function authenticateAdmin(
+ request: FastifyRequest,
+ reply: FastifyReply,
+): Promise {
+ try {
+ await request.jwtVerify();
+ const payload = request.user as { isAdmin?: boolean };
+ if (!payload.isAdmin) {
+ reply.code(403).send({ success: false, error: 'Forbidden', code: 'FORBIDDEN' });
+ }
+ } catch {
+ reply.code(401).send({ success: false, error: 'Unauthorized', code: 'UNAUTHORIZED' });
+ }
+}
diff --git a/evodron/packages/api/src/middleware/helpers.ts b/evodron/packages/api/src/middleware/helpers.ts
new file mode 100644
index 00000000..0a9e06a4
--- /dev/null
+++ b/evodron/packages/api/src/middleware/helpers.ts
@@ -0,0 +1,35 @@
+import crypto from 'crypto';
+
+/**
+ * Hash an IP address so it is never stored in plaintext.
+ */
+export function hashIp(ip: string): string {
+ return crypto.createHash('sha256').update(ip).digest('hex');
+}
+
+/**
+ * Generate a random alphanumeric string of the given length.
+ */
+export function randomCode(length = 8): string {
+ const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
+ let result = '';
+ const bytes = crypto.randomBytes(length);
+ for (let i = 0; i < length; i++) {
+ result += chars[bytes[i]! % chars.length];
+ }
+ return result;
+}
+
+/**
+ * Generate a UUIDv4.
+ */
+export function uuid(): string {
+ return crypto.randomUUID();
+}
+
+/**
+ * Return the current ISO timestamp.
+ */
+export function now(): string {
+ return new Date().toISOString();
+}
diff --git a/evodron/packages/api/src/routes/admin.ts b/evodron/packages/api/src/routes/admin.ts
new file mode 100644
index 00000000..045c1789
--- /dev/null
+++ b/evodron/packages/api/src/routes/admin.ts
@@ -0,0 +1,102 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import { eq, and, isNull, desc } from 'drizzle-orm';
+import { getDb, schema } from '@evodron/db';
+import { authenticateAdmin } from '../middleware/auth';
+import { uuid, now } from '../middleware/helpers';
+
+export async function adminRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── GET /admin/abuse-flags ────────────────────────────────────────────────
+
+ app.get(
+ '/abuse-flags',
+ { preHandler: [authenticateAdmin] },
+ async (_req: FastifyRequest, reply: FastifyReply) => {
+ const flags = await db
+ .select()
+ .from(schema.abuseFlags)
+ .where(isNull(schema.abuseFlags.resolvedAt))
+ .orderBy(desc(schema.abuseFlags.flaggedAt))
+ .all();
+
+ return reply.send({ success: true, data: { flags } });
+ },
+ );
+
+ // ── POST /admin/abuse-flags/:id/resolve ───────────────────────────────────
+
+ app.post(
+ '/abuse-flags/:id/resolve',
+ { preHandler: [authenticateAdmin] },
+ async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
+ const { id } = req.params;
+
+ await db
+ .update(schema.abuseFlags)
+ .set({ resolvedAt: now() })
+ .where(eq(schema.abuseFlags.id, id));
+
+ return reply.send({ success: true, data: { message: 'Flag resolved' } });
+ },
+ );
+
+ // ── POST /admin/users/:id/ban ─────────────────────────────────────────────
+
+ app.post(
+ '/users/:id/ban',
+ { preHandler: [authenticateAdmin] },
+ async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
+ const { id } = req.params;
+ const timestamp = now();
+
+ await db
+ .update(schema.users)
+ .set({ isBanned: true, updatedAt: timestamp })
+ .where(eq(schema.users.id, id));
+
+ // Flag any pending referrals from this user as fraud
+ await db
+ .update(schema.referrals)
+ .set({ status: 'fraud' })
+ .where(
+ and(eq(schema.referrals.referrerId, id), eq(schema.referrals.status, 'pending')),
+ );
+
+ return reply.send({ success: true, data: { message: 'User banned' } });
+ },
+ );
+
+ // ── GET /admin/reward-rules ───────────────────────────────────────────────
+
+ app.get(
+ '/reward-rules',
+ { preHandler: [authenticateAdmin] },
+ async (_req: FastifyRequest, reply: FastifyReply) => {
+ const rules = await db.select().from(schema.rewardRules).all();
+ return reply.send({ success: true, data: { rules } });
+ },
+ );
+
+ // ── PATCH /admin/reward-rules/:id ─────────────────────────────────────────
+
+ app.patch(
+ '/reward-rules/:id',
+ { preHandler: [authenticateAdmin] },
+ async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
+ const { id } = req.params;
+ const body = req.body as { credits?: number; active?: boolean; description?: string };
+ const timestamp = now();
+
+ const update: Partial = { updatedAt: timestamp };
+ if (typeof body.credits === 'number') update.credits = body.credits;
+ if (typeof body.active === 'boolean') update.active = body.active;
+ if (typeof body.description === 'string') update.description = body.description;
+
+ await db.update(schema.rewardRules).set(update).where(eq(schema.rewardRules.id, id));
+
+ const updated = await db.select().from(schema.rewardRules).where(eq(schema.rewardRules.id, id)).get();
+ return reply.send({ success: true, data: { rule: updated } });
+ },
+ );
+}
diff --git a/evodron/packages/api/src/routes/auth.ts b/evodron/packages/api/src/routes/auth.ts
new file mode 100644
index 00000000..73c6485e
--- /dev/null
+++ b/evodron/packages/api/src/routes/auth.ts
@@ -0,0 +1,327 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import bcrypt from 'bcryptjs';
+import crypto from 'crypto';
+import { eq, and, gt, isNull } from 'drizzle-orm';
+import { RegisterSchema, LoginSchema } from '@evodron/shared';
+import { getDb, schema } from '@evodron/db';
+import { hashIp, randomCode, uuid, now } from '../middleware/helpers';
+
+const BCRYPT_ROUNDS = 12;
+const REFRESH_EXPIRY_DAYS = 30;
+
+export async function authRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── POST /auth/register ──────────────────────────────────────────────────
+
+ app.post(
+ '/register',
+ {
+ config: { rateLimit: { max: 20, timeWindow: '1 minute' } },
+ },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const parsed = RegisterSchema.safeParse(req.body);
+ if (!parsed.success) {
+ return reply.code(400).send({
+ success: false,
+ error: 'Invalid input',
+ code: 'VALIDATION_ERROR',
+ details: parsed.error.flatten(),
+ });
+ }
+
+ const { email, username, password, referralCode } = parsed.data;
+
+ // Check uniqueness
+ const existing = await db
+ .select({ id: schema.users.id })
+ .from(schema.users)
+ .where(eq(schema.users.email, email.toLowerCase()))
+ .get();
+
+ if (existing) {
+ return reply.code(409).send({
+ success: false,
+ error: 'Email already registered',
+ code: 'EMAIL_EXISTS',
+ });
+ }
+
+ const existingUsername = await db
+ .select({ id: schema.users.id })
+ .from(schema.users)
+ .where(eq(schema.users.username, username))
+ .get();
+
+ if (existingUsername) {
+ return reply.code(409).send({
+ success: false,
+ error: 'Username already taken',
+ code: 'USERNAME_EXISTS',
+ });
+ }
+
+ // Resolve referrer
+ let referrerId: string | undefined;
+ if (referralCode) {
+ const referrer = await db
+ .select({ id: schema.users.id })
+ .from(schema.users)
+ .where(eq(schema.users.referralCode, referralCode))
+ .get();
+
+ if (!referrer) {
+ return reply.code(400).send({
+ success: false,
+ error: 'Invalid referral code',
+ code: 'INVALID_REFERRAL',
+ });
+ }
+ referrerId = referrer.id;
+ }
+
+ // Hash password
+ const passwordHash = await bcrypt.hash(password, BCRYPT_ROUNDS);
+ const userId = uuid();
+ const userReferralCode = randomCode(8);
+ const timestamp = now();
+
+ // Create user
+ await db.insert(schema.users).values({
+ id: userId,
+ email: email.toLowerCase(),
+ username,
+ passwordHash,
+ referralCode: userReferralCode,
+ referredBy: referrerId ?? null,
+ createdAt: timestamp,
+ updatedAt: timestamp,
+ });
+
+ // Create referral record
+ if (referrerId) {
+ // Anti-self-referral (cannot refer yourself)
+ if (referrerId === userId) {
+ // This cannot happen here since user doesn't exist yet, but guard anyway
+ } else {
+ await db.insert(schema.referrals).values({
+ id: uuid(),
+ referrerId,
+ refereeId: userId,
+ status: 'pending',
+ createdAt: timestamp,
+ });
+
+ // Onboarding reward for referee
+ const onboardingRule = await db
+ .select()
+ .from(schema.rewardRules)
+ .where(
+ and(
+ eq(schema.rewardRules.trigger, 'referral_onboarding'),
+ eq(schema.rewardRules.active, true),
+ ),
+ )
+ .get();
+
+ if (onboardingRule) {
+ await db.insert(schema.rewards).values({
+ id: uuid(),
+ userId,
+ type: 'referral_onboarding',
+ amount: onboardingRule.credits,
+ source: `Referral onboarding from code ${referralCode}`,
+ createdAt: timestamp,
+ });
+
+ await db
+ .update(schema.users)
+ .set({ credits: onboardingRule.credits, updatedAt: timestamp })
+ .where(eq(schema.users.id, userId));
+ }
+ }
+ }
+
+ // Track IP
+ const ip = (req.headers['x-forwarded-for'] as string) || req.ip || '0.0.0.0';
+ const ipHash = hashIp(ip.split(',')[0]!.trim());
+
+ await db.insert(schema.ipRegistry).values({
+ id: uuid(),
+ ipHash,
+ userId,
+ seenAt: timestamp,
+ });
+
+ // Detect suspicious IP reuse (same IP already used for multiple accounts)
+ const ipCount = (
+ await db
+ .select({ userId: schema.ipRegistry.userId })
+ .from(schema.ipRegistry)
+ .where(eq(schema.ipRegistry.ipHash, ipHash))
+ ).length;
+
+ if (ipCount > 5) {
+ await db.insert(schema.abuseFlags).values({
+ id: uuid(),
+ userId,
+ reason: 'ip_reuse',
+ detail: `IP hash ${ipHash} has been seen for ${ipCount} accounts`,
+ flaggedAt: timestamp,
+ });
+ }
+
+ // Issue tokens
+ const tokens = await issueTokens(app, db, userId, false);
+
+ return reply.code(201).send({
+ success: true,
+ data: { ...tokens, userId, username, referralCode: userReferralCode },
+ });
+ },
+ );
+
+ // ── POST /auth/login ─────────────────────────────────────────────────────
+
+ app.post(
+ '/login',
+ {
+ config: { rateLimit: { max: 20, timeWindow: '1 minute' } },
+ },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const parsed = LoginSchema.safeParse(req.body);
+ if (!parsed.success) {
+ return reply.code(400).send({ success: false, error: 'Invalid input', code: 'VALIDATION_ERROR' });
+ }
+
+ const { email, password } = parsed.data;
+
+ const user = await db
+ .select()
+ .from(schema.users)
+ .where(eq(schema.users.email, email.toLowerCase()))
+ .get();
+
+ if (!user) {
+ // Constant-time response to prevent user enumeration
+ await bcrypt.hash('dummy', 1);
+ return reply.code(401).send({ success: false, error: 'Invalid credentials', code: 'INVALID_CREDENTIALS' });
+ }
+
+ if (user.isBanned) {
+ return reply.code(403).send({ success: false, error: 'Account suspended', code: 'ACCOUNT_BANNED' });
+ }
+
+ const valid = await bcrypt.compare(password, user.passwordHash);
+ if (!valid) {
+ return reply.code(401).send({ success: false, error: 'Invalid credentials', code: 'INVALID_CREDENTIALS' });
+ }
+
+ const tokens = await issueTokens(app, db, user.id, user.isAdmin);
+
+ return reply.send({
+ success: true,
+ data: { ...tokens, userId: user.id, username: user.username },
+ });
+ },
+ );
+
+ // ── POST /auth/refresh ───────────────────────────────────────────────────
+
+ app.post('/refresh', async (req: FastifyRequest, reply: FastifyReply) => {
+ const body = req.body as { refreshToken?: string };
+ const refreshToken = body?.refreshToken;
+
+ if (!refreshToken) {
+ return reply.code(400).send({ success: false, error: 'refreshToken required', code: 'MISSING_TOKEN' });
+ }
+
+ const tokenHash = hashToken(refreshToken);
+ const expiry = new Date().toISOString();
+
+ const stored = await db
+ .select()
+ .from(schema.refreshTokens)
+ .where(
+ and(
+ eq(schema.refreshTokens.tokenHash, tokenHash),
+ gt(schema.refreshTokens.expiresAt, expiry),
+ isNull(schema.refreshTokens.revokedAt),
+ ),
+ )
+ .get();
+
+ if (!stored) {
+ return reply.code(401).send({ success: false, error: 'Invalid or expired refresh token', code: 'INVALID_TOKEN' });
+ }
+
+ const user = await db
+ .select({ id: schema.users.id, isAdmin: schema.users.isAdmin, isBanned: schema.users.isBanned })
+ .from(schema.users)
+ .where(eq(schema.users.id, stored.userId))
+ .get();
+
+ if (!user || user.isBanned) {
+ return reply.code(403).send({ success: false, error: 'Account suspended', code: 'ACCOUNT_BANNED' });
+ }
+
+ // Revoke old token
+ await db
+ .update(schema.refreshTokens)
+ .set({ revokedAt: now() })
+ .where(eq(schema.refreshTokens.id, stored.id));
+
+ const tokens = await issueTokens(app, db, user.id, user.isAdmin);
+ return reply.send({ success: true, data: tokens });
+ });
+
+ // ── POST /auth/logout ────────────────────────────────────────────────────
+
+ app.post('/logout', async (req: FastifyRequest, reply: FastifyReply) => {
+ const body = req.body as { refreshToken?: string };
+ const refreshToken = body?.refreshToken;
+
+ if (refreshToken) {
+ const tokenHash = hashToken(refreshToken);
+ await db
+ .update(schema.refreshTokens)
+ .set({ revokedAt: now() })
+ .where(eq(schema.refreshTokens.tokenHash, tokenHash));
+ }
+
+ return reply.send({ success: true, data: { message: 'Logged out' } });
+ });
+}
+
+// ─── Helpers ──────────────────────────────────────────────────────────────────
+
+function hashToken(token: string): string {
+ return crypto.createHash('sha256').update(token).digest('hex');
+}
+
+async function issueTokens(
+ app: FastifyInstance,
+ db: ReturnType,
+ userId: string,
+ isAdmin: boolean,
+) {
+ const accessToken = app.jwt.sign({ sub: userId, isAdmin }, { expiresIn: '15m' });
+
+ const rawRefresh = crypto.randomBytes(48).toString('hex');
+ const tokenHash = hashToken(rawRefresh);
+ const expiresAt = new Date(Date.now() + REFRESH_EXPIRY_DAYS * 86400000).toISOString();
+
+ await db.insert(schema.refreshTokens).values({
+ id: uuid(),
+ userId,
+ tokenHash,
+ expiresAt,
+ createdAt: now(),
+ });
+
+ return {
+ accessToken,
+ refreshToken: rawRefresh,
+ expiresIn: 900,
+ };
+}
diff --git a/evodron/packages/api/src/routes/referrals.ts b/evodron/packages/api/src/routes/referrals.ts
new file mode 100644
index 00000000..f42c59ec
--- /dev/null
+++ b/evodron/packages/api/src/routes/referrals.ts
@@ -0,0 +1,109 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import { eq, and } from 'drizzle-orm';
+import { getDb, schema } from '@evodron/db';
+import { authenticate } from '../middleware/auth';
+
+export async function referralRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── GET /referrals/code ──────────────────────────────────────────────────
+
+ app.get(
+ '/code',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+
+ const user = await db
+ .select({ referralCode: schema.users.referralCode })
+ .from(schema.users)
+ .where(eq(schema.users.id, userId))
+ .get();
+
+ if (!user) {
+ return reply.code(404).send({ success: false, error: 'User not found', code: 'NOT_FOUND' });
+ }
+
+ const base = process.env['EVODRON_REFERRAL_BASE_URL'] ?? 'https://evodron.io';
+ const link = `${base}/ref/${user.referralCode}`;
+
+ return reply.send({ success: true, data: { code: user.referralCode, link } });
+ },
+ );
+
+ // ── GET /referrals/stats ─────────────────────────────────────────────────
+
+ app.get(
+ '/stats',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+
+ const user = await db
+ .select({ referralCode: schema.users.referralCode })
+ .from(schema.users)
+ .where(eq(schema.users.id, userId))
+ .get();
+
+ if (!user) {
+ return reply.code(404).send({ success: false, error: 'User not found', code: 'NOT_FOUND' });
+ }
+
+ const allReferrals = await db
+ .select({
+ id: schema.referrals.id,
+ refereeId: schema.referrals.refereeId,
+ status: schema.referrals.status,
+ createdAt: schema.referrals.createdAt,
+ })
+ .from(schema.referrals)
+ .where(eq(schema.referrals.referrerId, userId))
+ .all();
+
+ // Fetch referee usernames
+ const referralEntries = await Promise.all(
+ allReferrals.map(async (r) => {
+ const referee = await db
+ .select({ username: schema.users.username })
+ .from(schema.users)
+ .where(eq(schema.users.id, r.refereeId))
+ .get();
+ return {
+ id: r.id,
+ refereeUsername: referee?.username ?? '(deleted)',
+ status: r.status,
+ createdAt: r.createdAt,
+ };
+ }),
+ );
+
+ const totalCreditsEarned = (
+ await db
+ .select({ amount: schema.rewards.amount })
+ .from(schema.rewards)
+ .where(
+ and(
+ eq(schema.rewards.userId, userId),
+ eq(schema.rewards.type, 'referral_active'),
+ ),
+ )
+ .all()
+ ).reduce((sum, r) => sum + r.amount, 0);
+
+ const base = process.env['EVODRON_REFERRAL_BASE_URL'] ?? 'https://evodron.io';
+
+ return reply.send({
+ success: true,
+ data: {
+ code: user.referralCode,
+ link: `${base}/ref/${user.referralCode}`,
+ totalReferrals: allReferrals.length,
+ activeReferrals: allReferrals.filter((r) => r.status !== 'pending').length,
+ pendingReferrals: allReferrals.filter((r) => r.status === 'pending').length,
+ totalCreditsEarned,
+ referrals: referralEntries,
+ },
+ });
+ },
+ );
+}
diff --git a/evodron/packages/api/src/routes/rewards.ts b/evodron/packages/api/src/routes/rewards.ts
new file mode 100644
index 00000000..0267ed98
--- /dev/null
+++ b/evodron/packages/api/src/routes/rewards.ts
@@ -0,0 +1,58 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import { eq, desc } from 'drizzle-orm';
+import { getDb, schema } from '@evodron/db';
+import { authenticate } from '../middleware/auth';
+
+export async function rewardRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── GET /rewards ─────────────────────────────────────────────────────────
+
+ app.get(
+ '/',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+
+ const rewardList = await db
+ .select()
+ .from(schema.rewards)
+ .where(eq(schema.rewards.userId, userId))
+ .orderBy(desc(schema.rewards.createdAt))
+ .all();
+
+ const total = rewardList.reduce((sum, r) => sum + r.amount, 0);
+
+ return reply.send({
+ success: true,
+ data: {
+ total,
+ rewards: rewardList,
+ },
+ });
+ },
+ );
+
+ // ── GET /rewards/rules ────────────────────────────────────────────────────
+
+ app.get(
+ '/rules',
+ { preHandler: [authenticate] },
+ async (_req: FastifyRequest, reply: FastifyReply) => {
+ const rules = await db
+ .select({
+ id: schema.rewardRules.id,
+ name: schema.rewardRules.name,
+ trigger: schema.rewardRules.trigger,
+ credits: schema.rewardRules.credits,
+ active: schema.rewardRules.active,
+ description: schema.rewardRules.description,
+ })
+ .from(schema.rewardRules)
+ .where(eq(schema.rewardRules.active, true))
+ .all();
+
+ return reply.send({ success: true, data: { rules } });
+ },
+ );
+}
diff --git a/evodron/packages/api/src/routes/sessions.ts b/evodron/packages/api/src/routes/sessions.ts
new file mode 100644
index 00000000..8ab590d0
--- /dev/null
+++ b/evodron/packages/api/src/routes/sessions.ts
@@ -0,0 +1,243 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import { eq, and, isNotNull } from 'drizzle-orm';
+import { getDb, schema } from '@evodron/db';
+import { authenticate } from '../middleware/auth';
+import { uuid, now, hashIp } from '../middleware/helpers';
+import { StartSessionSchema, EndSessionSchema } from '@evodron/shared';
+
+export async function sessionRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── POST /sessions/start ─────────────────────────────────────────────────
+
+ app.post(
+ '/start',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+ const parsed = StartSessionSchema.safeParse(req.body);
+ if (!parsed.success) {
+ return reply.code(400).send({ success: false, error: 'Invalid input', code: 'VALIDATION_ERROR' });
+ }
+
+ const ip = (req.headers['x-forwarded-for'] as string) || req.ip || '0.0.0.0';
+ const ipHash = hashIp(ip.split(',')[0]!.trim());
+ const sessionId = uuid();
+ const timestamp = now();
+
+ await db.insert(schema.sessions).values({
+ id: sessionId,
+ userId,
+ startedAt: timestamp,
+ clientVersion: parsed.data.clientVersion ?? null,
+ ipHash,
+ });
+
+ // Record IP for abuse detection
+ await db.insert(schema.ipRegistry).values({
+ id: uuid(),
+ ipHash,
+ userId,
+ seenAt: timestamp,
+ });
+
+ return reply.code(201).send({ success: true, data: { sessionId } });
+ },
+ );
+
+ // ── POST /sessions/end ───────────────────────────────────────────────────
+
+ app.post(
+ '/end',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+ const parsed = EndSessionSchema.safeParse(req.body);
+ if (!parsed.success) {
+ return reply.code(400).send({ success: false, error: 'Invalid input', code: 'VALIDATION_ERROR' });
+ }
+
+ const { sessionId, commandsCount } = parsed.data;
+ const timestamp = now();
+
+ const session = await db
+ .select()
+ .from(schema.sessions)
+ .where(and(eq(schema.sessions.id, sessionId), eq(schema.sessions.userId, userId)))
+ .get();
+
+ if (!session) {
+ return reply.code(404).send({ success: false, error: 'Session not found', code: 'NOT_FOUND' });
+ }
+
+ await db
+ .update(schema.sessions)
+ .set({ endedAt: timestamp, commandsCount })
+ .where(eq(schema.sessions.id, sessionId));
+
+ // Check if a referral should be activated
+ await checkAndActivateReferral(db, userId, timestamp);
+
+ // Check milestones
+ await checkMilestones(db, userId, timestamp);
+
+ return reply.send({ success: true, data: { sessionId } });
+ },
+ );
+}
+
+// ─── Referral activation ──────────────────────────────────────────────────────
+
+async function checkAndActivateReferral(
+ db: ReturnType,
+ userId: string,
+ timestamp: string,
+) {
+ const minSessions = parseInt(process.env['EVODRON_REWARD_MIN_SESSIONS'] ?? '3', 10);
+
+ const completedSessions = await db
+ .select({ id: schema.sessions.id })
+ .from(schema.sessions)
+ .where(and(eq(schema.sessions.userId, userId), isNotNull(schema.sessions.endedAt)))
+ .all();
+
+ if (completedSessions.length < minSessions) return;
+
+ // Look for pending referral where this user is the referee
+ const referral = await db
+ .select()
+ .from(schema.referrals)
+ .where(
+ and(eq(schema.referrals.refereeId, userId), eq(schema.referrals.status, 'pending')),
+ )
+ .get();
+
+ if (!referral) return;
+
+ // Activate referral
+ await db
+ .update(schema.referrals)
+ .set({ status: 'active', activatedAt: timestamp })
+ .where(eq(schema.referrals.id, referral.id));
+
+ // Get reward rule for referrer
+ const referrerRule = await db
+ .select()
+ .from(schema.rewardRules)
+ .where(
+ and(
+ eq(schema.rewardRules.trigger, 'referral_active'),
+ eq(schema.rewardRules.active, true),
+ ),
+ )
+ .get();
+
+ if (referrerRule) {
+ // Credit referrer
+ await db.insert(schema.rewards).values({
+ id: uuid(),
+ userId: referral.referrerId,
+ type: 'referral_active',
+ amount: referrerRule.credits,
+ source: `Referral activated: ${userId}`,
+ createdAt: timestamp,
+ });
+
+ const referrer = await db
+ .select({ credits: schema.users.credits })
+ .from(schema.users)
+ .where(eq(schema.users.id, referral.referrerId))
+ .get();
+
+ if (referrer) {
+ await db
+ .update(schema.users)
+ .set({
+ credits: referrer.credits + referrerRule.credits,
+ updatedAt: timestamp,
+ })
+ .where(eq(schema.users.id, referral.referrerId));
+ }
+
+ // Mark referral as rewarded
+ await db
+ .update(schema.referrals)
+ .set({ status: 'rewarded', rewardedAt: timestamp })
+ .where(eq(schema.referrals.id, referral.id));
+ }
+}
+
+// ─── Milestone check ──────────────────────────────────────────────────────────
+
+async function checkMilestones(
+ db: ReturnType,
+ userId: string,
+ timestamp: string,
+) {
+ const completedCount = (
+ await db
+ .select({ id: schema.sessions.id })
+ .from(schema.sessions)
+ .where(eq(schema.sessions.userId, userId))
+ .all()
+ ).length;
+
+ const milestoneTrigger = `milestone_${completedCount}_sessions`;
+
+ const rule = await db
+ .select()
+ .from(schema.rewardRules)
+ .where(
+ and(
+ eq(schema.rewardRules.trigger, milestoneTrigger),
+ eq(schema.rewardRules.active, true),
+ ),
+ )
+ .get();
+
+ if (!rule) return;
+
+ // Only award once — check if already awarded
+ const alreadyAwarded = await db
+ .select({ id: schema.rewards.id })
+ .from(schema.rewards)
+ .where(
+ and(
+ eq(schema.rewards.userId, userId),
+ eq(schema.rewards.source, milestoneTrigger),
+ ),
+ )
+ .get();
+
+ if (alreadyAwarded) return;
+
+ await db.insert(schema.rewards).values({
+ id: uuid(),
+ userId,
+ type: 'milestone',
+ amount: rule.credits,
+ source: milestoneTrigger,
+ createdAt: timestamp,
+ });
+
+ const user = await db
+ .select({ credits: schema.users.credits })
+ .from(schema.users)
+ .where(eq(schema.users.id, userId))
+ .get();
+
+ if (user) {
+ const newCredits = user.credits + rule.credits;
+ const newLevel = computeLevel(newCredits);
+ await db
+ .update(schema.users)
+ .set({ credits: newCredits, level: newLevel, updatedAt: timestamp })
+ .where(eq(schema.users.id, userId));
+ }
+}
+
+function computeLevel(credits: number): 'bronze' | 'silver' | 'gold' {
+ if (credits >= 1000) return 'gold';
+ if (credits >= 300) return 'silver';
+ return 'bronze';
+}
diff --git a/evodron/packages/api/src/routes/stats.ts b/evodron/packages/api/src/routes/stats.ts
new file mode 100644
index 00000000..84aa0fc6
--- /dev/null
+++ b/evodron/packages/api/src/routes/stats.ts
@@ -0,0 +1,52 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import { eq } from 'drizzle-orm';
+import { getDb, schema } from '@evodron/db';
+import { authenticate } from '../middleware/auth';
+
+export async function statsRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── GET /stats ────────────────────────────────────────────────────────────
+
+ app.get(
+ '/',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+
+ const user = await db
+ .select({
+ credits: schema.users.credits,
+ level: schema.users.level,
+ createdAt: schema.users.createdAt,
+ })
+ .from(schema.users)
+ .where(eq(schema.users.id, userId))
+ .get();
+
+ if (!user) {
+ return reply.code(404).send({ success: false, error: 'User not found', code: 'NOT_FOUND' });
+ }
+
+ const sessionList = await db
+ .select({ commandsCount: schema.sessions.commandsCount })
+ .from(schema.sessions)
+ .where(eq(schema.sessions.userId, userId))
+ .all();
+
+ const totalSessions = sessionList.length;
+ const totalCommands = sessionList.reduce((s, r) => s + r.commandsCount, 0);
+
+ return reply.send({
+ success: true,
+ data: {
+ totalSessions,
+ totalCommands,
+ totalCredits: user.credits,
+ level: user.level,
+ joinedAt: user.createdAt,
+ },
+ });
+ },
+ );
+}
diff --git a/evodron/packages/api/src/routes/users.ts b/evodron/packages/api/src/routes/users.ts
new file mode 100644
index 00000000..fbd54565
--- /dev/null
+++ b/evodron/packages/api/src/routes/users.ts
@@ -0,0 +1,70 @@
+import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
+import { eq } from 'drizzle-orm';
+import { getDb, schema } from '@evodron/db';
+import { authenticate } from '../middleware/auth';
+
+export async function userRoutes(app: FastifyInstance) {
+ const db = getDb();
+
+ // ── GET /users/me ────────────────────────────────────────────────────────
+
+ app.get(
+ '/me',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+
+ const user = await db
+ .select({
+ id: schema.users.id,
+ email: schema.users.email,
+ username: schema.users.username,
+ referralCode: schema.users.referralCode,
+ credits: schema.users.credits,
+ level: schema.users.level,
+ createdAt: schema.users.createdAt,
+ })
+ .from(schema.users)
+ .where(eq(schema.users.id, userId))
+ .get();
+
+ if (!user) {
+ return reply.code(404).send({ success: false, error: 'User not found', code: 'NOT_FOUND' });
+ }
+
+ const referralLink = buildReferralLink(user.referralCode);
+
+ return reply.send({
+ success: true,
+ data: { ...user, referralLink },
+ });
+ },
+ );
+
+ // ── PATCH /users/me/consent ──────────────────────────────────────────────
+
+ app.patch(
+ '/me/consent',
+ { preHandler: [authenticate] },
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { sub: userId } = req.user as { sub: string };
+ const body = req.body as { consentMetrics?: boolean };
+
+ if (typeof body?.consentMetrics !== 'boolean') {
+ return reply.code(400).send({ success: false, error: 'consentMetrics (boolean) required', code: 'VALIDATION_ERROR' });
+ }
+
+ await db
+ .update(schema.users)
+ .set({ consentMetrics: body.consentMetrics, updatedAt: new Date().toISOString() })
+ .where(eq(schema.users.id, userId));
+
+ return reply.send({ success: true, data: { consentMetrics: body.consentMetrics } });
+ },
+ );
+}
+
+function buildReferralLink(code: string): string {
+ const base = process.env['EVODRON_REFERRAL_BASE_URL'] ?? 'https://evodron.io';
+ return `${base}/ref/${code}`;
+}
diff --git a/evodron/packages/api/tsconfig.json b/evodron/packages/api/tsconfig.json
new file mode 100644
index 00000000..18803392
--- /dev/null
+++ b/evodron/packages/api/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "commonjs",
+ "lib": ["ES2020"],
+ "outDir": "dist",
+ "rootDir": "src",
+ "strict": true,
+ "esModuleInterop": true,
+ "declaration": true,
+ "sourceMap": true,
+ "paths": {
+ "@evodron/shared": ["../shared/src"],
+ "@evodron/db": ["../db/src"]
+ }
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/evodron/packages/api/vitest.config.mts b/evodron/packages/api/vitest.config.mts
new file mode 100644
index 00000000..3d27b8ad
--- /dev/null
+++ b/evodron/packages/api/vitest.config.mts
@@ -0,0 +1,15 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+ resolve: {
+ alias: {
+ '@evodron/shared': import.meta.dirname + '/../shared/src/index.ts',
+ '@evodron/db': import.meta.dirname + '/../db/src/index.ts',
+ },
+ },
+ test: {
+ environment: 'node',
+ globals: false,
+ testTimeout: 30000,
+ },
+});
diff --git a/evodron/packages/cli/package.json b/evodron/packages/cli/package.json
new file mode 100644
index 00000000..957c5c82
--- /dev/null
+++ b/evodron/packages/cli/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "@evodron/cli",
+ "version": "0.1.0",
+ "description": "EVODRON CLI — the evodron command",
+ "bin": {
+ "evodron": "./dist/bin/evodron.js"
+ },
+ "main": "dist/index.js",
+ "scripts": {
+ "build": "tsc",
+ "dev": "tsx watch src/bin/evodron.ts",
+ "start": "node dist/bin/evodron.js",
+ "test": "vitest run",
+ "lint": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@evodron/shared": "*",
+ "chalk": "^5.3.0",
+ "commander": "^12.0.0",
+ "dotenv": "^16.4.5",
+ "node-fetch": "^3.3.2"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.25",
+ "tsx": "^4.7.1",
+ "typescript": "^5.3.3",
+ "vitest": "^4.1.10"
+ }
+}
diff --git a/evodron/packages/cli/src/bin/evodron.ts b/evodron/packages/cli/src/bin/evodron.ts
new file mode 100644
index 00000000..44cd7feb
--- /dev/null
+++ b/evodron/packages/cli/src/bin/evodron.ts
@@ -0,0 +1,27 @@
+#!/usr/bin/env node
+import 'dotenv/config';
+import { program } from 'commander';
+import { splash } from '../ui/splash';
+import { registerAuthCommands } from '../commands/auth';
+import { registerReferralCommands } from '../commands/referral';
+import { registerRewardCommands } from '../commands/rewards';
+import { registerStatsCommands } from '../commands/stats';
+import { registerRunCommand } from '../commands/run';
+
+splash();
+
+program
+ .name('evodron')
+ .description('EVODRON — AI-powered developer platform\n\nNote: AI coding features are powered by the GitHub Copilot CLI (third-party component, not affiliated with EVODRON).')
+ .version('0.1.0');
+
+registerAuthCommands(program);
+registerReferralCommands(program);
+registerRewardCommands(program);
+registerStatsCommands(program);
+registerRunCommand(program);
+
+program.parseAsync(process.argv).catch((err: unknown) => {
+ console.error('Error:', err instanceof Error ? err.message : String(err));
+ process.exit(1);
+});
diff --git a/evodron/packages/cli/src/commands/auth.ts b/evodron/packages/cli/src/commands/auth.ts
new file mode 100644
index 00000000..77c61b7d
--- /dev/null
+++ b/evodron/packages/cli/src/commands/auth.ts
@@ -0,0 +1,153 @@
+import { Command } from 'commander';
+import chalk from 'chalk';
+import * as readline from 'readline';
+import { apiRequest } from '../services/api';
+import { loadConfig, saveConfig, clearConfig } from '../services/config';
+import type { ApiResponse, AuthTokens } from '@evodron/shared';
+
+export function registerAuthCommands(program: Command): void {
+ const auth = program.command('auth').description('Manage your EVODRON account');
+
+ // ── evodron auth register ────────────────────────────────────────────────
+
+ auth
+ .command('register')
+ .description('Create a new EVODRON account')
+ .option('--ref ', 'Referral code from a friend')
+ .action(async (opts: { ref?: string }) => {
+ console.log(chalk.bold('\n✨ Create your EVODRON account\n'));
+
+ const email = await prompt('Email: ');
+ const username = await prompt('Username: ');
+ const password = await promptPassword('Password (min 8 chars): ');
+
+ const body: Record = { email, username, password };
+ if (opts.ref) body['referralCode'] = opts.ref;
+
+ const res = await apiRequest>(
+ '/auth/register',
+ { method: 'POST', body: JSON.stringify(body) },
+ );
+
+ if (!res.success) {
+ console.error(chalk.red(`\n❌ Registration failed: ${res.error}`));
+ process.exit(1);
+ }
+
+ saveConfig({
+ accessToken: res.data.accessToken,
+ refreshToken: res.data.refreshToken,
+ userId: res.data.userId,
+ username: res.data.username,
+ });
+
+ console.log(chalk.green(`\n✅ Welcome to EVODRON, ${res.data.username}!`));
+ if (opts.ref) {
+ console.log(chalk.yellow('🎁 You received onboarding credits for joining via referral!'));
+ }
+ console.log(chalk.dim(`\nYour referral code: ${chalk.bold(res.data.referralCode)}`));
+ });
+
+ // ── evodron auth login ───────────────────────────────────────────────────
+
+ auth
+ .command('login')
+ .description('Log in to your EVODRON account')
+ .action(async () => {
+ console.log(chalk.bold('\n🔑 Log in to EVODRON\n'));
+ const email = await prompt('Email: ');
+ const password = await promptPassword('Password: ');
+
+ const res = await apiRequest>(
+ '/auth/login',
+ { method: 'POST', body: JSON.stringify({ email, password }) },
+ );
+
+ if (!res.success) {
+ console.error(chalk.red(`\n❌ Login failed: ${res.error}`));
+ process.exit(1);
+ }
+
+ saveConfig({
+ accessToken: res.data.accessToken,
+ refreshToken: res.data.refreshToken,
+ userId: res.data.userId,
+ username: res.data.username,
+ });
+
+ console.log(chalk.green(`\n✅ Logged in as ${res.data.username}`));
+ });
+
+ // ── evodron auth logout ──────────────────────────────────────────────────
+
+ auth
+ .command('logout')
+ .description('Log out of EVODRON')
+ .action(async () => {
+ const config = loadConfig();
+ if (config.refreshToken) {
+ await apiRequest('/auth/logout', {
+ method: 'POST',
+ body: JSON.stringify({ refreshToken: config.refreshToken }),
+ }).catch(() => {
+ // best effort
+ });
+ }
+ clearConfig();
+ console.log(chalk.green('\n✅ Logged out'));
+ });
+
+ // ── evodron auth status ──────────────────────────────────────────────────
+
+ auth
+ .command('status')
+ .description('Show current login status')
+ .action(() => {
+ const config = loadConfig();
+ if (config.username && config.accessToken) {
+ console.log(chalk.green(`\n✅ Logged in as ${chalk.bold(config.username)}`));
+ } else {
+ console.log(chalk.yellow('\n⚠️ Not logged in. Run: evodron auth login'));
+ }
+ });
+}
+
+// ─── Prompt helpers ───────────────────────────────────────────────────────────
+
+function prompt(question: string): Promise {
+ return new Promise((resolve) => {
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
+ rl.question(question, (answer) => {
+ rl.close();
+ resolve(answer.trim());
+ });
+ });
+}
+
+function promptPassword(question: string): Promise {
+ return new Promise((resolve) => {
+ process.stdout.write(question);
+ let password = '';
+ process.stdin.setRawMode?.(true);
+ process.stdin.resume();
+ process.stdin.setEncoding('utf8');
+
+ const onData = (ch: string) => {
+ if (ch === '\r' || ch === '\n') {
+ process.stdin.setRawMode?.(false);
+ process.stdin.pause();
+ process.stdin.removeListener('data', onData);
+ process.stdout.write('\n');
+ resolve(password);
+ } else if (ch === '\u0003') {
+ process.exit();
+ } else if (ch === '\u007f') {
+ password = password.slice(0, -1);
+ } else {
+ password += ch;
+ }
+ };
+
+ process.stdin.on('data', onData);
+ });
+}
diff --git a/evodron/packages/cli/src/commands/referral.ts b/evodron/packages/cli/src/commands/referral.ts
new file mode 100644
index 00000000..b443da6c
--- /dev/null
+++ b/evodron/packages/cli/src/commands/referral.ts
@@ -0,0 +1,70 @@
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { apiRequest } from '../services/api';
+import type { ApiResponse, ReferralStats } from '@evodron/shared';
+
+export function registerReferralCommands(program: Command): void {
+ const referral = program
+ .command('referral')
+ .description('Manage your EVODRON referrals');
+
+ // ── evodron referral code ────────────────────────────────────────────────
+
+ referral
+ .command('code')
+ .description('Show your referral code and link')
+ .action(async () => {
+ const res = await apiRequest>(
+ '/referrals/code',
+ { auth: true },
+ );
+
+ if (!res.success) {
+ console.error(chalk.red(`❌ ${res.error}`));
+ process.exit(1);
+ }
+
+ console.log(chalk.bold('\n🔗 Your EVODRON Referral\n'));
+ console.log(` Code : ${chalk.cyan(res.data.code)}`);
+ console.log(` Link : ${chalk.cyan(res.data.link)}`);
+ console.log(chalk.dim('\n Share your link and earn credits when friends become active users!\n'));
+ });
+
+ // ── evodron referral stats ────────────────────────────────────────────────
+
+ referral
+ .command('stats')
+ .description('Show your referral statistics')
+ .action(async () => {
+ const res = await apiRequest>('/referrals/stats', { auth: true });
+
+ if (!res.success) {
+ console.error(chalk.red(`❌ ${res.error}`));
+ process.exit(1);
+ }
+
+ const d = res.data;
+
+ console.log(chalk.bold('\n📊 Referral Dashboard\n'));
+ console.log(` Code : ${chalk.cyan(d.code)}`);
+ console.log(` Link : ${chalk.cyan(d.link)}`);
+ console.log(` Total referrals: ${chalk.white(d.totalReferrals)}`);
+ console.log(` Active : ${chalk.green(d.activeReferrals)}`);
+ console.log(` Pending : ${chalk.yellow(d.pendingReferrals)}`);
+ console.log(` Credits earned : ${chalk.yellow(d.totalCreditsEarned + ' ⚡')}`);
+
+ if (d.referrals.length > 0) {
+ console.log(chalk.bold('\n Referred users:\n'));
+ for (const r of d.referrals) {
+ const status =
+ r.status === 'active' || r.status === 'rewarded'
+ ? chalk.green(r.status)
+ : r.status === 'fraud'
+ ? chalk.red(r.status)
+ : chalk.yellow(r.status);
+ console.log(` • ${chalk.white(r.refereeUsername)} — ${status}`);
+ }
+ }
+ console.log();
+ });
+}
diff --git a/evodron/packages/cli/src/commands/rewards.ts b/evodron/packages/cli/src/commands/rewards.ts
new file mode 100644
index 00000000..da7120b1
--- /dev/null
+++ b/evodron/packages/cli/src/commands/rewards.ts
@@ -0,0 +1,67 @@
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { apiRequest } from '../services/api';
+import type { ApiResponse, Reward } from '@evodron/shared';
+
+export function registerRewardCommands(program: Command): void {
+ const rewards = program
+ .command('rewards')
+ .description('View your EVODRON credits and reward history');
+
+ rewards
+ .command('history')
+ .alias('ls')
+ .description('Show your reward history')
+ .action(async () => {
+ const res = await apiRequest>(
+ '/rewards',
+ { auth: true },
+ );
+
+ if (!res.success) {
+ console.error(chalk.red(`❌ ${res.error}`));
+ process.exit(1);
+ }
+
+ console.log(chalk.bold('\n⚡ EVODRON Credits\n'));
+ console.log(` Total balance : ${chalk.yellow(res.data.total + ' credits')}`);
+
+ if (res.data.rewards.length === 0) {
+ console.log(chalk.dim('\n No rewards yet. Refer friends to earn credits!\n'));
+ return;
+ }
+
+ console.log(chalk.bold('\n History:\n'));
+ for (const r of res.data.rewards) {
+ const date = new Date(r.createdAt).toLocaleDateString();
+ console.log(
+ ` ${chalk.dim(date)} ${chalk.green('+' + r.amount + ' ⚡')} ${chalk.dim(r.source)}`,
+ );
+ }
+ console.log();
+ });
+
+ rewards
+ .command('rules')
+ .description('Show active reward rules')
+ .action(async () => {
+ const res = await apiRequest }>>(
+ '/rewards/rules',
+ { auth: true },
+ );
+
+ if (!res.success) {
+ console.error(chalk.red(`❌ ${res.error}`));
+ process.exit(1);
+ }
+
+ console.log(chalk.bold('\n📋 Active Reward Rules\n'));
+ for (const rule of res.data.rules) {
+ console.log(` • ${chalk.cyan(rule.name)} — ${chalk.yellow(rule.credits + ' credits')}`);
+ if (rule.description) {
+ console.log(` ${chalk.dim(rule.description)}`);
+ }
+ }
+ console.log(chalk.dim('\n ⚠️ Credits are virtual and have no monetary value.\n'));
+ });
+}
diff --git a/evodron/packages/cli/src/commands/run.ts b/evodron/packages/cli/src/commands/run.ts
new file mode 100644
index 00000000..49eba94f
--- /dev/null
+++ b/evodron/packages/cli/src/commands/run.ts
@@ -0,0 +1,116 @@
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { spawn } from 'child_process';
+import { loadConfig } from '../services/config';
+import { apiRequest } from '../services/api';
+import type { ApiResponse } from '@evodron/shared';
+
+/**
+ * `evodron run` — delegates to the GitHub Copilot CLI binary.
+ *
+ * The GitHub Copilot CLI is a third-party component, © GitHub, Inc.
+ * EVODRON is not affiliated with GitHub or Microsoft.
+ *
+ * If `ghcs` (GitHub Copilot CLI) is not installed, the command prints
+ * installation instructions and exits.
+ */
+export function registerRunCommand(program: Command): void {
+ program
+ .command('run [args...]')
+ .description(
+ 'Run the GitHub Copilot CLI AI assistant (third-party component)\n' +
+ ' All arguments are passed directly to the GitHub Copilot CLI.\n' +
+ ' Example: evodron run -- "explain this code"',
+ )
+ .allowUnknownOption()
+ .action(async (_args: string[], _opts: unknown, cmd: Command) => {
+ const config = loadConfig();
+ if (!config.accessToken) {
+ console.error(chalk.yellow('\n⚠️ Please log in first: evodron auth login\n'));
+ process.exit(1);
+ }
+
+ // Record session start
+ let sessionId: string | undefined;
+ try {
+ if (config.accessToken) {
+ const startRes = await apiRequest>('/sessions/start', {
+ method: 'POST',
+ auth: true,
+ body: JSON.stringify({ clientVersion: '0.1.0' }),
+ });
+ if (startRes.success) {
+ sessionId = startRes.data.sessionId;
+ }
+ }
+ } catch {
+ // Non-fatal: continue even if session tracking fails
+ }
+
+ const rawArgs = process.argv.slice(process.argv.indexOf('run') + 1).filter((a) => a !== '--');
+ const copilotBin = findCopilotCli();
+
+ if (!copilotBin) {
+ console.error(chalk.red('\n❌ GitHub Copilot CLI not found.\n'));
+ console.log(
+ chalk.dim(
+ ' Install it with:\n' +
+ ' curl -fsSL https://gh.io/copilot-install | bash\n\n' +
+ ' GitHub Copilot CLI is a third-party product by GitHub, Inc.\n' +
+ ' EVODRON is not affiliated with GitHub or Microsoft.\n',
+ ),
+ );
+ await endSession(sessionId, 0);
+ process.exit(1);
+ }
+
+ console.log(chalk.dim(`\n Launching GitHub Copilot CLI [third-party]...\n`));
+
+ const child = spawn(copilotBin, rawArgs, {
+ stdio: 'inherit',
+ env: process.env,
+ });
+
+ let commandsCount = 0;
+
+ child.on('close', async (code) => {
+ commandsCount++;
+ await endSession(sessionId, commandsCount);
+ process.exit(code ?? 0);
+ });
+
+ child.on('error', async (err) => {
+ console.error(chalk.red(`\n❌ Failed to launch Copilot CLI: ${err.message}\n`));
+ await endSession(sessionId, commandsCount);
+ process.exit(1);
+ });
+ });
+}
+
+function findCopilotCli(): string | null {
+ const candidates = ['ghcs', 'gh-copilot', 'gh copilot'];
+ const { execSync } = require('child_process') as typeof import('child_process');
+
+ for (const bin of ['ghcs', 'gh']) {
+ try {
+ execSync(`which ${bin}`, { stdio: 'ignore' });
+ return bin;
+ } catch {
+ // not found
+ }
+ }
+ return null;
+}
+
+async function endSession(sessionId: string | undefined, commandsCount: number): Promise {
+ if (!sessionId) return;
+ try {
+ await apiRequest('/sessions/end', {
+ method: 'POST',
+ auth: true,
+ body: JSON.stringify({ sessionId, commandsCount }),
+ });
+ } catch {
+ // Non-fatal
+ }
+}
diff --git a/evodron/packages/cli/src/commands/stats.ts b/evodron/packages/cli/src/commands/stats.ts
new file mode 100644
index 00000000..1328a2fd
--- /dev/null
+++ b/evodron/packages/cli/src/commands/stats.ts
@@ -0,0 +1,35 @@
+import { Command } from 'commander';
+import chalk from 'chalk';
+import { apiRequest } from '../services/api';
+import type { ApiResponse, UserStats } from '@evodron/shared';
+
+export function registerStatsCommands(program: Command): void {
+ program
+ .command('stats')
+ .description('Show your EVODRON usage statistics')
+ .action(async () => {
+ const res = await apiRequest>('/stats', { auth: true });
+
+ if (!res.success) {
+ console.error(chalk.red(`❌ ${res.error}`));
+ process.exit(1);
+ }
+
+ const d = res.data;
+
+ const levelColor =
+ d.level === 'gold'
+ ? chalk.yellow
+ : d.level === 'silver'
+ ? chalk.gray
+ : chalk.rgb(205, 127, 50); // bronze
+
+ console.log(chalk.bold('\n📈 Your EVODRON Stats\n'));
+ console.log(` Level : ${levelColor(d.level.toUpperCase() + ' ★')}`);
+ console.log(` Total sessions : ${chalk.white(d.totalSessions)}`);
+ console.log(` Total commands : ${chalk.white(d.totalCommands)}`);
+ console.log(` Credits : ${chalk.yellow(d.totalCredits + ' ⚡')}`);
+ console.log(` Member since : ${chalk.dim(new Date(d.joinedAt).toLocaleDateString())}`);
+ console.log();
+ });
+}
diff --git a/evodron/packages/cli/src/services/api.ts b/evodron/packages/cli/src/services/api.ts
new file mode 100644
index 00000000..4c50149d
--- /dev/null
+++ b/evodron/packages/cli/src/services/api.ts
@@ -0,0 +1,71 @@
+import { loadConfig, getApiUrl, saveConfig } from './config';
+
+interface ApiOptions {
+ auth?: boolean;
+}
+
+export async function apiRequest(
+ path: string,
+ options: RequestInit & ApiOptions = {},
+): Promise {
+ const { auth = false, ...fetchOptions } = options;
+ const url = `${getApiUrl()}${path}`;
+ const headers: Record = {
+ 'Content-Type': 'application/json',
+ ...(fetchOptions.headers as Record),
+ };
+
+ if (auth) {
+ const config = loadConfig();
+ if (!config.accessToken) {
+ throw new Error('Not logged in. Run: evodron auth login');
+ }
+ headers['Authorization'] = 'Bearer ' + config.accessToken!;
+ }
+
+ const res = await fetch(url, { ...fetchOptions, headers });
+
+ // Handle 401 — try to refresh token
+ if (res.status === 401 && auth) {
+ const refreshed = await tryRefreshToken();
+ if (refreshed) {
+ const config = loadConfig();
+ headers['Authorization'] = 'Bearer ' + config.accessToken!;
+ const retry = await fetch(url, { ...fetchOptions, headers });
+ return retry.json() as Promise;
+ } else {
+ throw new Error('Session expired. Please login again: evodron auth login');
+ }
+ }
+
+ return res.json() as Promise;
+}
+
+async function tryRefreshToken(): Promise {
+ const config = loadConfig();
+ if (!config.refreshToken) return false;
+
+ try {
+ const res = await fetch(`${getApiUrl()}/auth/refresh`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ refreshToken: config.refreshToken }),
+ });
+ const data = (await res.json()) as {
+ success: boolean;
+ data?: { accessToken: string; refreshToken: string };
+ };
+
+ if (data.success && data.data) {
+ saveConfig({
+ ...config,
+ accessToken: data.data.accessToken,
+ refreshToken: data.data.refreshToken,
+ });
+ return true;
+ }
+ } catch {
+ // ignore
+ }
+ return false;
+}
diff --git a/evodron/packages/cli/src/services/config.ts b/evodron/packages/cli/src/services/config.ts
new file mode 100644
index 00000000..38d9cbd3
--- /dev/null
+++ b/evodron/packages/cli/src/services/config.ts
@@ -0,0 +1,49 @@
+import fs from 'fs';
+import path from 'path';
+import os from 'os';
+
+interface Config {
+ accessToken?: string;
+ refreshToken?: string;
+ userId?: string;
+ username?: string;
+ apiUrl?: string;
+}
+
+function configDir(): string {
+ return process.env['EVODRON_CONFIG_DIR'] ?? path.join(os.homedir(), '.evodron');
+}
+
+function configFile(): string {
+ return path.join(configDir(), 'config.json');
+}
+
+export function loadConfig(): Config {
+ try {
+ const raw = fs.readFileSync(configFile(), 'utf-8');
+ return JSON.parse(raw) as Config;
+ } catch {
+ return {};
+ }
+}
+
+export function saveConfig(config: Config): void {
+ const dir = configDir();
+ if (!fs.existsSync(dir)) {
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
+ }
+ fs.writeFileSync(configFile(), JSON.stringify(config, null, 2), { mode: 0o600 });
+}
+
+export function getApiUrl(): string {
+ const config = loadConfig();
+ return config.apiUrl ?? process.env['EVODRON_API_URL'] ?? 'http://localhost:3000';
+}
+
+export function clearConfig(): void {
+ try {
+ fs.unlinkSync(configFile());
+ } catch {
+ // ignore
+ }
+}
diff --git a/evodron/packages/cli/src/ui/splash.ts b/evodron/packages/cli/src/ui/splash.ts
new file mode 100644
index 00000000..cb7a6aea
--- /dev/null
+++ b/evodron/packages/cli/src/ui/splash.ts
@@ -0,0 +1,24 @@
+import chalk from 'chalk';
+
+const LOGO = `
+ ███████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███╗ ██╗
+ ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔══██╗██╔═══██╗████╗ ██║
+ █████╗ ██║ ██║██║ ██║██║ ██║██████╔╝██║ ██║██╔██╗ ██║
+ ██╔══╝ ╚██╗ ██╔╝██║ ██║██║ ██║██╔══██╗██║ ██║██║╚██╗██║
+ ███████╗ ╚████╔╝ ╚██████╔╝██████╔╝██║ ██║╚██████╔╝██║ ╚████║
+ ╚══════╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
+`;
+
+export function splash(): void {
+ if (process.env['EVODRON_NO_SPLASH'] === '1') return;
+ process.stdout.write(chalk.cyan(LOGO));
+ process.stdout.write(chalk.dim(' AI-powered developer platform ') + chalk.yellow('v0.1.0') + '\n');
+ process.stdout.write(chalk.dim(' ─────────────────────────────────────────────────────────────\n'));
+ process.stdout.write(
+ chalk.dim(
+ ' AI features powered by GitHub Copilot CLI (third-party, © GitHub, Inc.)\n',
+ ),
+ );
+ process.stdout.write(chalk.dim(' EVODRON is not affiliated with GitHub or Microsoft.\n'));
+ process.stdout.write(chalk.dim(' ─────────────────────────────────────────────────────────────\n\n'));
+}
diff --git a/evodron/packages/cli/tsconfig.json b/evodron/packages/cli/tsconfig.json
new file mode 100644
index 00000000..572b9fe3
--- /dev/null
+++ b/evodron/packages/cli/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "commonjs",
+ "lib": ["ES2020"],
+ "outDir": "dist",
+ "rootDir": "src",
+ "strict": true,
+ "esModuleInterop": true,
+ "declaration": true,
+ "sourceMap": true,
+ "paths": {
+ "@evodron/shared": ["../shared/src"]
+ }
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/evodron/packages/db/package.json b/evodron/packages/db/package.json
new file mode 100644
index 00000000..2b775c63
--- /dev/null
+++ b/evodron/packages/db/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "@evodron/db",
+ "version": "0.1.0",
+ "description": "EVODRON database schema and migrations",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "scripts": {
+ "build": "tsc",
+ "migrate": "tsx src/migrate.ts",
+ "seed": "tsx src/seed.ts"
+ },
+ "dependencies": {
+ "better-sqlite3": "^9.4.3",
+ "drizzle-orm": "^0.45.2",
+ "nanoid": "^5.0.4"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "^7.6.8",
+ "drizzle-kit": "^0.20.14",
+ "tsx": "^4.7.1",
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/evodron/packages/db/src/client.ts b/evodron/packages/db/src/client.ts
new file mode 100644
index 00000000..207d75f2
--- /dev/null
+++ b/evodron/packages/db/src/client.ts
@@ -0,0 +1,23 @@
+import Database from 'better-sqlite3';
+import { drizzle } from 'drizzle-orm/better-sqlite3';
+import * as schema from './schema';
+
+let _db: ReturnType> | null = null;
+
+export function getDb(dbUrl?: string): ReturnType> {
+ if (_db) return _db;
+
+ const url = dbUrl ?? process.env['EVODRON_DB_URL'] ?? 'file:./evodron.db';
+ // Strip "file:" prefix for better-sqlite3
+ const filePath = url.startsWith('file:') ? url.slice(5) : url;
+
+ const sqlite = new Database(filePath);
+ sqlite.pragma('journal_mode = WAL');
+ sqlite.pragma('foreign_keys = ON');
+
+ _db = drizzle(sqlite, { schema });
+ return _db;
+}
+
+export { schema };
+export type Db = ReturnType;
diff --git a/evodron/packages/db/src/index.ts b/evodron/packages/db/src/index.ts
new file mode 100644
index 00000000..ecaa1564
--- /dev/null
+++ b/evodron/packages/db/src/index.ts
@@ -0,0 +1,2 @@
+export * from './schema';
+export * from './client';
diff --git a/evodron/packages/db/src/migrate.ts b/evodron/packages/db/src/migrate.ts
new file mode 100644
index 00000000..3e873536
--- /dev/null
+++ b/evodron/packages/db/src/migrate.ts
@@ -0,0 +1,103 @@
+/**
+ * EVODRON database migration runner.
+ * Creates all tables if they do not exist.
+ */
+import Database from 'better-sqlite3';
+
+const url = process.env['EVODRON_DB_URL'] ?? 'file:./evodron.db';
+const filePath = url.startsWith('file:') ? url.slice(5) : url;
+
+const db = new Database(filePath);
+db.pragma('journal_mode = WAL');
+db.pragma('foreign_keys = ON');
+
+const migrations = [
+ `CREATE TABLE IF NOT EXISTS users (
+ id TEXT PRIMARY KEY,
+ email TEXT NOT NULL UNIQUE,
+ username TEXT NOT NULL UNIQUE,
+ password_hash TEXT NOT NULL,
+ referral_code TEXT NOT NULL UNIQUE,
+ referred_by TEXT REFERENCES users(id),
+ credits INTEGER NOT NULL DEFAULT 0,
+ level TEXT NOT NULL DEFAULT 'bronze' CHECK(level IN ('bronze','silver','gold')),
+ is_admin INTEGER NOT NULL DEFAULT 0,
+ is_banned INTEGER NOT NULL DEFAULT 0,
+ consent_metrics INTEGER NOT NULL DEFAULT 0,
+ created_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL
+ )`,
+ `CREATE TABLE IF NOT EXISTS sessions (
+ id TEXT PRIMARY KEY,
+ user_id TEXT NOT NULL REFERENCES users(id),
+ started_at TEXT NOT NULL,
+ ended_at TEXT,
+ commands_count INTEGER NOT NULL DEFAULT 0,
+ client_version TEXT,
+ ip_hash TEXT
+ )`,
+ `CREATE TABLE IF NOT EXISTS referrals (
+ id TEXT PRIMARY KEY,
+ referrer_id TEXT NOT NULL REFERENCES users(id),
+ referee_id TEXT NOT NULL UNIQUE REFERENCES users(id),
+ status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','active','rewarded','fraud')),
+ activated_at TEXT,
+ rewarded_at TEXT,
+ created_at TEXT NOT NULL
+ )`,
+ `CREATE TABLE IF NOT EXISTS rewards (
+ id TEXT PRIMARY KEY,
+ user_id TEXT NOT NULL REFERENCES users(id),
+ type TEXT NOT NULL CHECK(type IN ('referral_active','referral_onboarding','milestone','manual')),
+ amount INTEGER NOT NULL,
+ source TEXT NOT NULL,
+ created_at TEXT NOT NULL
+ )`,
+ `CREATE TABLE IF NOT EXISTS reward_rules (
+ id TEXT PRIMARY KEY,
+ name TEXT NOT NULL UNIQUE,
+ trigger TEXT NOT NULL,
+ credits INTEGER NOT NULL,
+ active INTEGER NOT NULL DEFAULT 1,
+ description TEXT,
+ updated_at TEXT NOT NULL
+ )`,
+ `CREATE TABLE IF NOT EXISTS abuse_flags (
+ id TEXT PRIMARY KEY,
+ user_id TEXT NOT NULL REFERENCES users(id),
+ reason TEXT NOT NULL,
+ detail TEXT,
+ resolved_at TEXT,
+ flagged_at TEXT NOT NULL
+ )`,
+ `CREATE TABLE IF NOT EXISTS ip_registry (
+ id TEXT PRIMARY KEY,
+ ip_hash TEXT NOT NULL,
+ user_id TEXT NOT NULL REFERENCES users(id),
+ seen_at TEXT NOT NULL
+ )`,
+ `CREATE TABLE IF NOT EXISTS refresh_tokens (
+ id TEXT PRIMARY KEY,
+ user_id TEXT NOT NULL REFERENCES users(id),
+ token_hash TEXT NOT NULL UNIQUE,
+ expires_at TEXT NOT NULL,
+ created_at TEXT NOT NULL,
+ revoked_at TEXT
+ )`,
+ // Indexes
+ `CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id)`,
+ `CREATE INDEX IF NOT EXISTS idx_referrals_referrer ON referrals(referrer_id)`,
+ `CREATE INDEX IF NOT EXISTS idx_rewards_user_id ON rewards(user_id)`,
+ `CREATE INDEX IF NOT EXISTS idx_abuse_flags_user ON abuse_flags(user_id)`,
+ `CREATE INDEX IF NOT EXISTS idx_ip_registry_hash ON ip_registry(ip_hash)`,
+ `CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user ON refresh_tokens(user_id)`,
+];
+
+db.transaction(() => {
+ for (const sql of migrations) {
+ db.prepare(sql).run();
+ }
+})();
+
+console.log('✅ EVODRON database migrated successfully');
+db.close();
diff --git a/evodron/packages/db/src/schema.ts b/evodron/packages/db/src/schema.ts
new file mode 100644
index 00000000..0dbffbb9
--- /dev/null
+++ b/evodron/packages/db/src/schema.ts
@@ -0,0 +1,101 @@
+import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core';
+
+// ─── users ────────────────────────────────────────────────────────────────────
+
+export const users = sqliteTable('users', {
+ id: text('id').primaryKey(),
+ email: text('email').notNull().unique(),
+ username: text('username').notNull().unique(),
+ passwordHash: text('password_hash').notNull(),
+ referralCode: text('referral_code').notNull().unique(),
+ referredBy: text('referred_by').references(() => users.id),
+ credits: integer('credits').notNull().default(0),
+ level: text('level', { enum: ['bronze', 'silver', 'gold'] }).notNull().default('bronze'),
+ isAdmin: integer('is_admin', { mode: 'boolean' }).notNull().default(false),
+ isBanned: integer('is_banned', { mode: 'boolean' }).notNull().default(false),
+ consentMetrics: integer('consent_metrics', { mode: 'boolean' }).notNull().default(false),
+ createdAt: text('created_at').notNull(),
+ updatedAt: text('updated_at').notNull(),
+});
+
+// ─── sessions ─────────────────────────────────────────────────────────────────
+
+export const sessions = sqliteTable('sessions', {
+ id: text('id').primaryKey(),
+ userId: text('user_id').notNull().references(() => users.id),
+ startedAt: text('started_at').notNull(),
+ endedAt: text('ended_at'),
+ commandsCount: integer('commands_count').notNull().default(0),
+ clientVersion: text('client_version'),
+ ipHash: text('ip_hash'),
+});
+
+// ─── referrals ────────────────────────────────────────────────────────────────
+
+export const referrals = sqliteTable('referrals', {
+ id: text('id').primaryKey(),
+ referrerId: text('referrer_id').notNull().references(() => users.id),
+ refereeId: text('referee_id').notNull().unique().references(() => users.id),
+ status: text('status', { enum: ['pending', 'active', 'rewarded', 'fraud'] })
+ .notNull()
+ .default('pending'),
+ activatedAt: text('activated_at'),
+ rewardedAt: text('rewarded_at'),
+ createdAt: text('created_at').notNull(),
+});
+
+// ─── rewards ──────────────────────────────────────────────────────────────────
+
+export const rewards = sqliteTable('rewards', {
+ id: text('id').primaryKey(),
+ userId: text('user_id').notNull().references(() => users.id),
+ type: text('type', {
+ enum: ['referral_active', 'referral_onboarding', 'milestone', 'manual'],
+ }).notNull(),
+ amount: integer('amount').notNull(),
+ source: text('source').notNull(),
+ createdAt: text('created_at').notNull(),
+});
+
+// ─── reward_rules ─────────────────────────────────────────────────────────────
+
+export const rewardRules = sqliteTable('reward_rules', {
+ id: text('id').primaryKey(),
+ name: text('name').notNull().unique(),
+ trigger: text('trigger').notNull(),
+ credits: integer('credits').notNull(),
+ active: integer('active', { mode: 'boolean' }).notNull().default(true),
+ description: text('description'),
+ updatedAt: text('updated_at').notNull(),
+});
+
+// ─── abuse_flags ──────────────────────────────────────────────────────────────
+
+export const abuseFlags = sqliteTable('abuse_flags', {
+ id: text('id').primaryKey(),
+ userId: text('user_id').notNull().references(() => users.id),
+ reason: text('reason').notNull(),
+ detail: text('detail'),
+ resolvedAt: text('resolved_at'),
+ flaggedAt: text('flagged_at').notNull(),
+});
+
+// ─── ip_registry ──────────────────────────────────────────────────────────────
+
+export const ipRegistry = sqliteTable('ip_registry', {
+ id: text('id').primaryKey(),
+ ipHash: text('ip_hash').notNull(),
+ userId: text('user_id').notNull().references(() => users.id),
+ seenAt: text('seen_at').notNull(),
+});
+
+// ─── refresh_tokens ───────────────────────────────────────────────────────────
+
+export const refreshTokens = sqliteTable('refresh_tokens', {
+ id: text('id').primaryKey(),
+ userId: text('user_id').notNull().references(() => users.id),
+ tokenHash: text('token_hash').notNull().unique(),
+ expiresAt: text('expires_at').notNull(),
+ createdAt: text('created_at').notNull(),
+ revokedAt: text('revoked_at'),
+});
diff --git a/evodron/packages/db/src/seed.ts b/evodron/packages/db/src/seed.ts
new file mode 100644
index 00000000..98a49b38
--- /dev/null
+++ b/evodron/packages/db/src/seed.ts
@@ -0,0 +1,53 @@
+/**
+ * EVODRON database seeder — populates default reward rules.
+ */
+import Database from 'better-sqlite3';
+import { randomUUID } from 'crypto';
+
+const url = process.env['EVODRON_DB_URL'] ?? 'file:./evodron.db';
+const filePath = url.startsWith('file:') ? url.slice(5) : url;
+const db = new Database(filePath);
+const now = new Date().toISOString();
+
+const defaultRules = [
+ {
+ id: randomUUID(),
+ name: 'referral_active_referrer',
+ trigger: 'referral_active',
+ credits: 100,
+ active: 1,
+ description: 'Credits awarded to the referrer when a referee reaches active status',
+ updated_at: now,
+ },
+ {
+ id: randomUUID(),
+ name: 'referral_onboarding_referee',
+ trigger: 'referral_onboarding',
+ credits: 50,
+ active: 1,
+ description: 'Onboarding credits awarded to a new user who joined via referral',
+ updated_at: now,
+ },
+ {
+ id: randomUUID(),
+ name: 'milestone_10_sessions',
+ trigger: 'milestone_10_sessions',
+ credits: 25,
+ active: 1,
+ description: 'Bonus credits for completing 10 sessions',
+ updated_at: now,
+ },
+];
+
+const stmt = db.prepare(`
+ INSERT OR IGNORE INTO reward_rules (id, name, trigger, credits, active, description, updated_at)
+ VALUES (@id, @name, @trigger, @credits, @active, @description, @updated_at)
+`);
+
+const insert = db.transaction(() => {
+ for (const rule of defaultRules) stmt.run(rule);
+});
+insert();
+
+console.log('✅ Default reward rules seeded');
+db.close();
diff --git a/evodron/packages/db/tsconfig.json b/evodron/packages/db/tsconfig.json
new file mode 100644
index 00000000..0b66e711
--- /dev/null
+++ b/evodron/packages/db/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "commonjs",
+ "lib": ["ES2020"],
+ "outDir": "dist",
+ "rootDir": "src",
+ "strict": true,
+ "esModuleInterop": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/evodron/packages/shared/package.json b/evodron/packages/shared/package.json
new file mode 100644
index 00000000..fb5c4d40
--- /dev/null
+++ b/evodron/packages/shared/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "@evodron/shared",
+ "version": "0.1.0",
+ "description": "Shared types and schemas for the EVODRON platform",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "scripts": {
+ "build": "tsc",
+ "dev": "tsc --watch"
+ },
+ "dependencies": {
+ "zod": "^3.22.4"
+ },
+ "devDependencies": {
+ "typescript": "^5.3.3"
+ }
+}
diff --git a/evodron/packages/shared/src/index.ts b/evodron/packages/shared/src/index.ts
new file mode 100644
index 00000000..9ea46a12
--- /dev/null
+++ b/evodron/packages/shared/src/index.ts
@@ -0,0 +1,120 @@
+import { z } from 'zod';
+
+// ─── User ────────────────────────────────────────────────────────────────────
+
+export const RegisterSchema = z.object({
+ email: z.string().email(),
+ username: z.string().min(3).max(32).regex(/^[a-zA-Z0-9_-]+$/),
+ password: z.string().min(8).max(128),
+ referralCode: z.string().length(8).optional(),
+});
+export type RegisterInput = z.infer;
+
+export const LoginSchema = z.object({
+ email: z.string().email(),
+ password: z.string().min(1),
+});
+export type LoginInput = z.infer;
+
+export interface UserPublic {
+ id: string;
+ email: string;
+ username: string;
+ referralCode: string;
+ credits: number;
+ level: UserLevel;
+ createdAt: string;
+}
+
+export type UserLevel = 'bronze' | 'silver' | 'gold';
+
+// ─── Session ─────────────────────────────────────────────────────────────────
+
+export const StartSessionSchema = z.object({
+ clientVersion: z.string().optional(),
+});
+export type StartSessionInput = z.infer;
+
+export const EndSessionSchema = z.object({
+ sessionId: z.string().uuid(),
+ commandsCount: z.number().int().min(0),
+});
+export type EndSessionInput = z.infer;
+
+// ─── Referral ────────────────────────────────────────────────────────────────
+
+export type ReferralStatus = 'pending' | 'active' | 'rewarded' | 'fraud';
+
+export interface ReferralStats {
+ code: string;
+ link: string;
+ totalReferrals: number;
+ activeReferrals: number;
+ pendingReferrals: number;
+ totalCreditsEarned: number;
+ referrals: ReferralEntry[];
+}
+
+export interface ReferralEntry {
+ id: string;
+ refereeUsername: string;
+ status: ReferralStatus;
+ createdAt: string;
+}
+
+// ─── Reward ──────────────────────────────────────────────────────────────────
+
+export type RewardType =
+ | 'referral_active'
+ | 'referral_onboarding'
+ | 'milestone'
+ | 'manual';
+
+export interface Reward {
+ id: string;
+ type: RewardType;
+ amount: number;
+ source: string;
+ createdAt: string;
+}
+
+export interface RewardRule {
+ id: string;
+ name: string;
+ trigger: string;
+ credits: number;
+ active: boolean;
+}
+
+// ─── Stats ───────────────────────────────────────────────────────────────────
+
+export interface UserStats {
+ totalSessions: number;
+ totalCommands: number;
+ totalCredits: number;
+ level: UserLevel;
+ joinedAt: string;
+}
+
+// ─── API Responses ───────────────────────────────────────────────────────────
+
+export interface ApiSuccess {
+ success: true;
+ data: T;
+}
+
+export interface ApiError {
+ success: false;
+ error: string;
+ code?: string;
+}
+
+export type ApiResponse = ApiSuccess | ApiError;
+
+// ─── Auth tokens ─────────────────────────────────────────────────────────────
+
+export interface AuthTokens {
+ accessToken: string;
+ refreshToken: string;
+ expiresIn: number;
+}
diff --git a/evodron/packages/shared/tsconfig.json b/evodron/packages/shared/tsconfig.json
new file mode 100644
index 00000000..0b66e711
--- /dev/null
+++ b/evodron/packages/shared/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "commonjs",
+ "lib": ["ES2020"],
+ "outDir": "dist",
+ "rootDir": "src",
+ "strict": true,
+ "esModuleInterop": true,
+ "declaration": true,
+ "declarationMap": true,
+ "sourceMap": true
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/evodron/scripts/setup.sh b/evodron/scripts/setup.sh
new file mode 100755
index 00000000..490b9d38
--- /dev/null
+++ b/evodron/scripts/setup.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+# EVODRON Setup Script
+# Sets up the EVODRON platform for development.
+# Usage: bash scripts/setup.sh
+
+set -e
+
+cd "$(dirname "$0")/.."
+
+echo ""
+echo " ███████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███╗ ██╗"
+echo " ██╔════╝██║ ██║██╔═══██╗██╔══██╗██╔══██╗██╔═══██╗████╗ ██║"
+echo " █████╗ ██║ ██║██║ ██║██║ ██║██████╔╝██║ ██║██╔██╗ ██║"
+echo " ██╔══╝ ╚██╗ ██╔╝██║ ██║██║ ██║██╔══██╗██║ ██║██║╚██╗██║"
+echo " ███████╗ ╚████╔╝ ╚██████╔╝██████╔╝██║ ██║╚██████╔╝██║ ╚████║"
+echo " ╚══════╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝"
+echo ""
+echo " EVODRON Setup"
+echo " ─────────────────────────────────────────────────────────────────"
+echo ""
+
+# 1. Check Node.js
+if ! command -v node &>/dev/null; then
+ echo "❌ Node.js is required (>= 18). Please install it first."
+ exit 1
+fi
+
+NODE_VER=$(node -e "process.stdout.write(process.versions.node.split('.')[0])")
+if [ "$NODE_VER" -lt 18 ]; then
+ echo "❌ Node.js >= 18 required. Found: $(node --version)"
+ exit 1
+fi
+
+echo "✅ Node.js $(node --version) found"
+
+# 2. Copy .env if not exists
+if [ ! -f .env ]; then
+ cp .env.example .env
+ echo "✅ .env created from .env.example"
+ echo "⚠️ Edit .env and set a secure EVODRON_JWT_SECRET before starting the API."
+else
+ echo "✅ .env already exists"
+fi
+
+# 3. Install dependencies
+echo ""
+echo "📦 Installing dependencies..."
+npm install
+
+# 4. Run database migrations
+echo ""
+echo "🗄️ Running database migrations..."
+npm run db:migrate
+
+# 5. Seed default reward rules
+echo ""
+echo "🌱 Seeding default reward rules..."
+npm run db:seed
+
+echo ""
+echo "─────────────────────────────────────────────────────────────────"
+echo "✅ EVODRON setup complete!"
+echo ""
+echo " To start the API:"
+echo " npm run dev:api"
+echo ""
+echo " To use the CLI (after build):"
+echo " npm run build"
+echo " node packages/cli/dist/bin/evodron.js auth register"
+echo ""
+echo " ⚠️ Remember to set a secure EVODRON_JWT_SECRET in .env!"
+echo "─────────────────────────────────────────────────────────────────"
+echo ""
From 8d8ad293a0dfb95d3950c64bb59c0632891b3a53 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:01:46 +0000
Subject: [PATCH 04/13] fix: add workflow permissions and rate limit health
endpoint (CodeQL)
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
.github/workflows/ci.yml | 3 +++
EVODRON.md | 5 +++--
src/routes/health.js | 3 ++-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e8629a5f..0f5dd423 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,6 +5,9 @@ on:
branches: ["**"]
pull_request:
+permissions:
+ contents: read
+
jobs:
test:
runs-on: ubuntu-latest
diff --git a/EVODRON.md b/EVODRON.md
index c527a876..cd5086c7 100644
--- a/EVODRON.md
+++ b/EVODRON.md
@@ -38,7 +38,8 @@ evodron/
│ └── referral.js # /api/referral (link, stats, rewards, activate-use)
└── tests/
├── referral.test.js # Tests flux de parrainage
- └── anti-abuse.test.js # Tests anti-fraude
+ ├── anti-abuse.test.js # Tests anti-fraude
+ └── health.test.js # Tests endpoint /api/health
```
## Prérequis
@@ -102,7 +103,7 @@ Tous les tests utilisent une base SQLite en mémoire (`DB_PATH=:memory:`). Aucun
### Authentification JWT
-Passer le token dans le header `Authorization: ****** ou dans un cookie `token`.
+Passer le token JWT via le header HTTP `Authorization` (schéma `Bearer`) ou dans un cookie nommé `token`.
## Variables d'environnement
diff --git a/src/routes/health.js b/src/routes/health.js
index 54b1e0db..490b4557 100644
--- a/src/routes/health.js
+++ b/src/routes/health.js
@@ -2,6 +2,7 @@
const express = require('express');
const { getDb } = require('../db/database');
+const { apiLimiter } = require('../middleware/rateLimiter');
const router = express.Router();
@@ -10,7 +11,7 @@ const router = express.Router();
* Returns the application health status.
* No authentication required — used by load balancers and monitoring.
*/
-router.get('/', (req, res) => {
+router.get('/', apiLimiter, (req, res) => {
const status = { status: 'ok', version: process.env.npm_package_version || '1.0.0', timestamp: new Date().toISOString() };
try {
From 5f213c5570cbf86af7f9a7a9b3ed3cd0e5c8d2d7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:04:40 +0000
Subject: [PATCH 05/13] =?UTF-8?q?fix:=20code=20review=20=E2=80=94=20reject?=
=?UTF-8?q?ion=20sampling=20for=20random=20codes,=20referral=20stats,=20mi?=
=?UTF-8?q?lestone=20filter,=20cleanup?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
evodron/.env.example | 3 ---
evodron/docs/EVODRON.md | 1 -
evodron/packages/api/src/middleware/helpers.ts | 16 +++++++++++++---
evodron/packages/api/src/routes/referrals.ts | 2 +-
evodron/packages/api/src/routes/sessions.ts | 2 +-
evodron/packages/cli/src/commands/run.ts | 1 -
6 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/evodron/.env.example b/evodron/.env.example
index 0515a2d3..bd1f0f55 100644
--- a/evodron/.env.example
+++ b/evodron/.env.example
@@ -8,9 +8,6 @@
# Secret used to sign JWTs. Must be a long, random string (32+ chars).
EVODRON_JWT_SECRET=change-me-to-a-long-random-secret
-# Secret used to sign refresh tokens (different from JWT secret).
-EVODRON_REFRESH_SECRET=change-me-to-another-long-random-secret
-
# Port the API listens on.
EVODRON_API_PORT=3000
diff --git a/evodron/docs/EVODRON.md b/evodron/docs/EVODRON.md
index e92b19a9..b3f83ff7 100644
--- a/evodron/docs/EVODRON.md
+++ b/evodron/docs/EVODRON.md
@@ -154,7 +154,6 @@ See `.env.example` for all available variables.
| Variable | Required | Description |
|----------|----------|-------------|
| `EVODRON_JWT_SECRET` | Yes | JWT signing secret (32+ chars) |
-| `EVODRON_REFRESH_SECRET` | Yes | Refresh token secret |
| `EVODRON_DB_URL` | Yes | SQLite path or PostgreSQL URL |
| `EVODRON_API_URL` | CLI | API URL (used by CLI) |
| `EVODRON_REFERRAL_BASE_URL` | No | Base URL for referral links |
diff --git a/evodron/packages/api/src/middleware/helpers.ts b/evodron/packages/api/src/middleware/helpers.ts
index 0a9e06a4..0e806baf 100644
--- a/evodron/packages/api/src/middleware/helpers.ts
+++ b/evodron/packages/api/src/middleware/helpers.ts
@@ -9,13 +9,23 @@ export function hashIp(ip: string): string {
/**
* Generate a random alphanumeric string of the given length.
+ * Uses rejection sampling to avoid modulo bias.
*/
export function randomCode(length = 8): string {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789';
+ const charsLen = chars.length;
+ // Maximum value that produces unbiased output with rejection sampling
+ const maxUnbiased = 256 - (256 % charsLen);
let result = '';
- const bytes = crypto.randomBytes(length);
- for (let i = 0; i < length; i++) {
- result += chars[bytes[i]! % chars.length];
+ while (result.length < length) {
+ const bytes = crypto.randomBytes(length * 2); // over-generate to reduce rounds
+ for (let i = 0; i < bytes.length && result.length < length; i++) {
+ const byte = bytes[i]!;
+ // Reject bytes in the biased range
+ if (byte < maxUnbiased) {
+ result += chars[byte % charsLen];
+ }
+ }
}
return result;
}
diff --git a/evodron/packages/api/src/routes/referrals.ts b/evodron/packages/api/src/routes/referrals.ts
index f42c59ec..5743ebd9 100644
--- a/evodron/packages/api/src/routes/referrals.ts
+++ b/evodron/packages/api/src/routes/referrals.ts
@@ -98,7 +98,7 @@ export async function referralRoutes(app: FastifyInstance) {
code: user.referralCode,
link: `${base}/ref/${user.referralCode}`,
totalReferrals: allReferrals.length,
- activeReferrals: allReferrals.filter((r) => r.status !== 'pending').length,
+ activeReferrals: allReferrals.filter((r) => r.status === 'active' || r.status === 'rewarded').length,
pendingReferrals: allReferrals.filter((r) => r.status === 'pending').length,
totalCreditsEarned,
referrals: referralEntries,
diff --git a/evodron/packages/api/src/routes/sessions.ts b/evodron/packages/api/src/routes/sessions.ts
index 8ab590d0..6b5aebed 100644
--- a/evodron/packages/api/src/routes/sessions.ts
+++ b/evodron/packages/api/src/routes/sessions.ts
@@ -178,7 +178,7 @@ async function checkMilestones(
await db
.select({ id: schema.sessions.id })
.from(schema.sessions)
- .where(eq(schema.sessions.userId, userId))
+ .where(and(eq(schema.sessions.userId, userId), isNotNull(schema.sessions.endedAt)))
.all()
).length;
diff --git a/evodron/packages/cli/src/commands/run.ts b/evodron/packages/cli/src/commands/run.ts
index 49eba94f..e4832398 100644
--- a/evodron/packages/cli/src/commands/run.ts
+++ b/evodron/packages/cli/src/commands/run.ts
@@ -88,7 +88,6 @@ export function registerRunCommand(program: Command): void {
}
function findCopilotCli(): string | null {
- const candidates = ['ghcs', 'gh-copilot', 'gh copilot'];
const { execSync } = require('child_process') as typeof import('child_process');
for (const bin of ['ghcs', 'gh']) {
From d247100a3b97c51163e26f6c97f666004a67ef1f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:34:43 +0000
Subject: [PATCH 06/13] chore: prioritize workspace consolidation
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
evodron/packages/db/src/client.d.ts | 5 +
evodron/packages/db/src/client.js | 58 ++
evodron/packages/db/src/index.d.ts | 2 +
evodron/packages/db/src/index.js | 19 +
evodron/packages/db/src/schema.d.ts | 859 +++++++++++++++++++++++++
evodron/packages/db/src/schema.js | 89 +++
evodron/packages/shared/src/index.d.ts | 111 ++++
evodron/packages/shared/src/index.js | 24 +
package-lock.json | 4 +-
9 files changed, 1169 insertions(+), 2 deletions(-)
create mode 100644 evodron/packages/db/src/client.d.ts
create mode 100644 evodron/packages/db/src/client.js
create mode 100644 evodron/packages/db/src/index.d.ts
create mode 100644 evodron/packages/db/src/index.js
create mode 100644 evodron/packages/db/src/schema.d.ts
create mode 100644 evodron/packages/db/src/schema.js
create mode 100644 evodron/packages/shared/src/index.d.ts
create mode 100644 evodron/packages/shared/src/index.js
diff --git a/evodron/packages/db/src/client.d.ts b/evodron/packages/db/src/client.d.ts
new file mode 100644
index 00000000..5df41e4b
--- /dev/null
+++ b/evodron/packages/db/src/client.d.ts
@@ -0,0 +1,5 @@
+import { drizzle } from 'drizzle-orm/better-sqlite3';
+import * as schema from './schema';
+export declare function getDb(dbUrl?: string): ReturnType>;
+export { schema };
+export type Db = ReturnType;
diff --git a/evodron/packages/db/src/client.js b/evodron/packages/db/src/client.js
new file mode 100644
index 00000000..3e19027f
--- /dev/null
+++ b/evodron/packages/db/src/client.js
@@ -0,0 +1,58 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+ o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || (function () {
+ var ownKeys = function(o) {
+ ownKeys = Object.getOwnPropertyNames || function (o) {
+ var ar = [];
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
+ return ar;
+ };
+ return ownKeys(o);
+ };
+ return function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
+ __setModuleDefault(result, mod);
+ return result;
+ };
+})();
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.schema = void 0;
+exports.getDb = getDb;
+const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
+const better_sqlite3_2 = require("drizzle-orm/better-sqlite3");
+const schema = __importStar(require("./schema"));
+exports.schema = schema;
+let _db = null;
+function getDb(dbUrl) {
+ if (_db)
+ return _db;
+ const url = dbUrl ?? process.env['EVODRON_DB_URL'] ?? 'file:./evodron.db';
+ // Strip "file:" prefix for better-sqlite3
+ const filePath = url.startsWith('file:') ? url.slice(5) : url;
+ const sqlite = new better_sqlite3_1.default(filePath);
+ sqlite.pragma('journal_mode = WAL');
+ sqlite.pragma('foreign_keys = ON');
+ _db = (0, better_sqlite3_2.drizzle)(sqlite, { schema });
+ return _db;
+}
+//# sourceMappingURL=client.js.map
\ No newline at end of file
diff --git a/evodron/packages/db/src/index.d.ts b/evodron/packages/db/src/index.d.ts
new file mode 100644
index 00000000..ecaa1564
--- /dev/null
+++ b/evodron/packages/db/src/index.d.ts
@@ -0,0 +1,2 @@
+export * from './schema';
+export * from './client';
diff --git a/evodron/packages/db/src/index.js b/evodron/packages/db/src/index.js
new file mode 100644
index 00000000..2bf45469
--- /dev/null
+++ b/evodron/packages/db/src/index.js
@@ -0,0 +1,19 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./schema"), exports);
+__exportStar(require("./client"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/evodron/packages/db/src/schema.d.ts b/evodron/packages/db/src/schema.d.ts
new file mode 100644
index 00000000..f5c81e97
--- /dev/null
+++ b/evodron/packages/db/src/schema.d.ts
@@ -0,0 +1,859 @@
+export declare const users: any;
+export declare const sessions: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "sessions";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "sessions";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "user_id";
+ tableName: "sessions";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ startedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "started_at";
+ tableName: "sessions";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ endedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "ended_at";
+ tableName: "sessions";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ commandsCount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "commands_count";
+ tableName: "sessions";
+ dataType: "number";
+ columnType: "SQLiteInteger";
+ data: number;
+ driverParam: number;
+ notNull: true;
+ hasDefault: true;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: undefined;
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {}>;
+ clientVersion: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "client_version";
+ tableName: "sessions";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ ipHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "ip_hash";
+ tableName: "sessions";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
+export declare const referrals: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "referrals";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ referrerId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "referrer_id";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ refereeId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "referee_id";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "status";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: "pending" | "active" | "rewarded" | "fraud";
+ driverParam: string;
+ notNull: true;
+ hasDefault: true;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: ["pending", "active", "rewarded", "fraud"];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ activatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "activated_at";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ rewardedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "rewarded_at";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "created_at";
+ tableName: "referrals";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
+export declare const rewards: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "rewards";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "rewards";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "user_id";
+ tableName: "rewards";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ type: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "type";
+ tableName: "rewards";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: "manual" | "referral_active" | "referral_onboarding" | "milestone";
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: ["referral_active", "referral_onboarding", "milestone", "manual"];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ amount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "amount";
+ tableName: "rewards";
+ dataType: "number";
+ columnType: "SQLiteInteger";
+ data: number;
+ driverParam: number;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: undefined;
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {}>;
+ source: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "source";
+ tableName: "rewards";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "created_at";
+ tableName: "rewards";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
+export declare const rewardRules: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "reward_rules";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "reward_rules";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ name: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "name";
+ tableName: "reward_rules";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ trigger: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "trigger";
+ tableName: "reward_rules";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ credits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "credits";
+ tableName: "reward_rules";
+ dataType: "number";
+ columnType: "SQLiteInteger";
+ data: number;
+ driverParam: number;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: undefined;
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {}>;
+ active: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "active";
+ tableName: "reward_rules";
+ dataType: "boolean";
+ columnType: "SQLiteBoolean";
+ data: boolean;
+ driverParam: number;
+ notNull: true;
+ hasDefault: true;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: undefined;
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {}>;
+ description: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "description";
+ tableName: "reward_rules";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "updated_at";
+ tableName: "reward_rules";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
+export declare const abuseFlags: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "abuse_flags";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "abuse_flags";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "user_id";
+ tableName: "abuse_flags";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ reason: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "reason";
+ tableName: "abuse_flags";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ detail: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "detail";
+ tableName: "abuse_flags";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ resolvedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "resolved_at";
+ tableName: "abuse_flags";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ flaggedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "flagged_at";
+ tableName: "abuse_flags";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
+export declare const ipRegistry: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "ip_registry";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "ip_registry";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ ipHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "ip_hash";
+ tableName: "ip_registry";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "user_id";
+ tableName: "ip_registry";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ seenAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "seen_at";
+ tableName: "ip_registry";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
+export declare const refreshTokens: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
+ name: "refresh_tokens";
+ schema: undefined;
+ columns: {
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "id";
+ tableName: "refresh_tokens";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: true;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "user_id";
+ tableName: "refresh_tokens";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ tokenHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "token_hash";
+ tableName: "refresh_tokens";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ expiresAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "expires_at";
+ tableName: "refresh_tokens";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "created_at";
+ tableName: "refresh_tokens";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: true;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ revokedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
+ name: "revoked_at";
+ tableName: "refresh_tokens";
+ dataType: "string";
+ columnType: "SQLiteText";
+ data: string;
+ driverParam: string;
+ notNull: false;
+ hasDefault: false;
+ isPrimaryKey: false;
+ isAutoincrement: false;
+ hasRuntimeDefault: false;
+ enumValues: [string, ...string[]];
+ baseColumn: never;
+ identity: undefined;
+ generated: undefined;
+ }, {}, {
+ length: number | undefined;
+ }>;
+ };
+ dialect: "sqlite";
+}>;
diff --git a/evodron/packages/db/src/schema.js b/evodron/packages/db/src/schema.js
new file mode 100644
index 00000000..4514ae77
--- /dev/null
+++ b/evodron/packages/db/src/schema.js
@@ -0,0 +1,89 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.refreshTokens = exports.ipRegistry = exports.abuseFlags = exports.rewardRules = exports.rewards = exports.referrals = exports.sessions = exports.users = void 0;
+const sqlite_core_1 = require("drizzle-orm/sqlite-core");
+// ─── users ────────────────────────────────────────────────────────────────────
+exports.users = (0, sqlite_core_1.sqliteTable)('users', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ email: (0, sqlite_core_1.text)('email').notNull().unique(),
+ username: (0, sqlite_core_1.text)('username').notNull().unique(),
+ passwordHash: (0, sqlite_core_1.text)('password_hash').notNull(),
+ referralCode: (0, sqlite_core_1.text)('referral_code').notNull().unique(),
+ referredBy: (0, sqlite_core_1.text)('referred_by').references(() => exports.users.id),
+ credits: (0, sqlite_core_1.integer)('credits').notNull().default(0),
+ level: (0, sqlite_core_1.text)('level', { enum: ['bronze', 'silver', 'gold'] }).notNull().default('bronze'),
+ isAdmin: (0, sqlite_core_1.integer)('is_admin', { mode: 'boolean' }).notNull().default(false),
+ isBanned: (0, sqlite_core_1.integer)('is_banned', { mode: 'boolean' }).notNull().default(false),
+ consentMetrics: (0, sqlite_core_1.integer)('consent_metrics', { mode: 'boolean' }).notNull().default(false),
+ createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
+ updatedAt: (0, sqlite_core_1.text)('updated_at').notNull(),
+});
+// ─── sessions ─────────────────────────────────────────────────────────────────
+exports.sessions = (0, sqlite_core_1.sqliteTable)('sessions', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
+ startedAt: (0, sqlite_core_1.text)('started_at').notNull(),
+ endedAt: (0, sqlite_core_1.text)('ended_at'),
+ commandsCount: (0, sqlite_core_1.integer)('commands_count').notNull().default(0),
+ clientVersion: (0, sqlite_core_1.text)('client_version'),
+ ipHash: (0, sqlite_core_1.text)('ip_hash'),
+});
+// ─── referrals ────────────────────────────────────────────────────────────────
+exports.referrals = (0, sqlite_core_1.sqliteTable)('referrals', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ referrerId: (0, sqlite_core_1.text)('referrer_id').notNull().references(() => exports.users.id),
+ refereeId: (0, sqlite_core_1.text)('referee_id').notNull().unique().references(() => exports.users.id),
+ status: (0, sqlite_core_1.text)('status', { enum: ['pending', 'active', 'rewarded', 'fraud'] })
+ .notNull()
+ .default('pending'),
+ activatedAt: (0, sqlite_core_1.text)('activated_at'),
+ rewardedAt: (0, sqlite_core_1.text)('rewarded_at'),
+ createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
+});
+// ─── rewards ──────────────────────────────────────────────────────────────────
+exports.rewards = (0, sqlite_core_1.sqliteTable)('rewards', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
+ type: (0, sqlite_core_1.text)('type', {
+ enum: ['referral_active', 'referral_onboarding', 'milestone', 'manual'],
+ }).notNull(),
+ amount: (0, sqlite_core_1.integer)('amount').notNull(),
+ source: (0, sqlite_core_1.text)('source').notNull(),
+ createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
+});
+// ─── reward_rules ─────────────────────────────────────────────────────────────
+exports.rewardRules = (0, sqlite_core_1.sqliteTable)('reward_rules', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ name: (0, sqlite_core_1.text)('name').notNull().unique(),
+ trigger: (0, sqlite_core_1.text)('trigger').notNull(),
+ credits: (0, sqlite_core_1.integer)('credits').notNull(),
+ active: (0, sqlite_core_1.integer)('active', { mode: 'boolean' }).notNull().default(true),
+ description: (0, sqlite_core_1.text)('description'),
+ updatedAt: (0, sqlite_core_1.text)('updated_at').notNull(),
+});
+// ─── abuse_flags ──────────────────────────────────────────────────────────────
+exports.abuseFlags = (0, sqlite_core_1.sqliteTable)('abuse_flags', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
+ reason: (0, sqlite_core_1.text)('reason').notNull(),
+ detail: (0, sqlite_core_1.text)('detail'),
+ resolvedAt: (0, sqlite_core_1.text)('resolved_at'),
+ flaggedAt: (0, sqlite_core_1.text)('flagged_at').notNull(),
+});
+// ─── ip_registry ──────────────────────────────────────────────────────────────
+exports.ipRegistry = (0, sqlite_core_1.sqliteTable)('ip_registry', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ ipHash: (0, sqlite_core_1.text)('ip_hash').notNull(),
+ userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
+ seenAt: (0, sqlite_core_1.text)('seen_at').notNull(),
+});
+// ─── refresh_tokens ───────────────────────────────────────────────────────────
+exports.refreshTokens = (0, sqlite_core_1.sqliteTable)('refresh_tokens', {
+ id: (0, sqlite_core_1.text)('id').primaryKey(),
+ userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
+ tokenHash: (0, sqlite_core_1.text)('token_hash').notNull().unique(),
+ expiresAt: (0, sqlite_core_1.text)('expires_at').notNull(),
+ createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
+ revokedAt: (0, sqlite_core_1.text)('revoked_at'),
+});
+//# sourceMappingURL=schema.js.map
\ No newline at end of file
diff --git a/evodron/packages/shared/src/index.d.ts b/evodron/packages/shared/src/index.d.ts
new file mode 100644
index 00000000..8dd2c111
--- /dev/null
+++ b/evodron/packages/shared/src/index.d.ts
@@ -0,0 +1,111 @@
+import { z } from 'zod';
+export declare const RegisterSchema: z.ZodObject<{
+ email: z.ZodString;
+ username: z.ZodString;
+ password: z.ZodString;
+ referralCode: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ email: string;
+ username: string;
+ password: string;
+ referralCode?: string | undefined;
+}, {
+ email: string;
+ username: string;
+ password: string;
+ referralCode?: string | undefined;
+}>;
+export type RegisterInput = z.infer;
+export declare const LoginSchema: z.ZodObject<{
+ email: z.ZodString;
+ password: z.ZodString;
+}, "strip", z.ZodTypeAny, {
+ email: string;
+ password: string;
+}, {
+ email: string;
+ password: string;
+}>;
+export type LoginInput = z.infer;
+export interface UserPublic {
+ id: string;
+ email: string;
+ username: string;
+ referralCode: string;
+ credits: number;
+ level: UserLevel;
+ createdAt: string;
+}
+export type UserLevel = 'bronze' | 'silver' | 'gold';
+export declare const StartSessionSchema: z.ZodObject<{
+ clientVersion: z.ZodOptional;
+}, "strip", z.ZodTypeAny, {
+ clientVersion?: string | undefined;
+}, {
+ clientVersion?: string | undefined;
+}>;
+export type StartSessionInput = z.infer;
+export declare const EndSessionSchema: z.ZodObject<{
+ sessionId: z.ZodString;
+ commandsCount: z.ZodNumber;
+}, "strip", z.ZodTypeAny, {
+ sessionId: string;
+ commandsCount: number;
+}, {
+ sessionId: string;
+ commandsCount: number;
+}>;
+export type EndSessionInput = z.infer;
+export type ReferralStatus = 'pending' | 'active' | 'rewarded' | 'fraud';
+export interface ReferralStats {
+ code: string;
+ link: string;
+ totalReferrals: number;
+ activeReferrals: number;
+ pendingReferrals: number;
+ totalCreditsEarned: number;
+ referrals: ReferralEntry[];
+}
+export interface ReferralEntry {
+ id: string;
+ refereeUsername: string;
+ status: ReferralStatus;
+ createdAt: string;
+}
+export type RewardType = 'referral_active' | 'referral_onboarding' | 'milestone' | 'manual';
+export interface Reward {
+ id: string;
+ type: RewardType;
+ amount: number;
+ source: string;
+ createdAt: string;
+}
+export interface RewardRule {
+ id: string;
+ name: string;
+ trigger: string;
+ credits: number;
+ active: boolean;
+}
+export interface UserStats {
+ totalSessions: number;
+ totalCommands: number;
+ totalCredits: number;
+ level: UserLevel;
+ joinedAt: string;
+}
+export interface ApiSuccess {
+ success: true;
+ data: T;
+}
+export interface ApiError {
+ success: false;
+ error: string;
+ code?: string;
+}
+export type ApiResponse = ApiSuccess | ApiError;
+export interface AuthTokens {
+ accessToken: string;
+ refreshToken: string;
+ expiresIn: number;
+}
diff --git a/evodron/packages/shared/src/index.js b/evodron/packages/shared/src/index.js
new file mode 100644
index 00000000..0727b658
--- /dev/null
+++ b/evodron/packages/shared/src/index.js
@@ -0,0 +1,24 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.EndSessionSchema = exports.StartSessionSchema = exports.LoginSchema = exports.RegisterSchema = void 0;
+const zod_1 = require("zod");
+// ─── User ────────────────────────────────────────────────────────────────────
+exports.RegisterSchema = zod_1.z.object({
+ email: zod_1.z.string().email(),
+ username: zod_1.z.string().min(3).max(32).regex(/^[a-zA-Z0-9_-]+$/),
+ password: zod_1.z.string().min(8).max(128),
+ referralCode: zod_1.z.string().length(8).optional(),
+});
+exports.LoginSchema = zod_1.z.object({
+ email: zod_1.z.string().email(),
+ password: zod_1.z.string().min(1),
+});
+// ─── Session ─────────────────────────────────────────────────────────────────
+exports.StartSessionSchema = zod_1.z.object({
+ clientVersion: zod_1.z.string().optional(),
+});
+exports.EndSessionSchema = zod_1.z.object({
+ sessionId: zod_1.z.string().uuid(),
+ commandsCount: zod_1.z.number().int().min(0),
+});
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 098046cf..69b68ae0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "evodron-referral",
+ "name": "evodron",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "evodron-referral",
+ "name": "evodron",
"version": "1.0.0",
"dependencies": {
"bcryptjs": "^2.4.3",
From 7c9c38bb3bc1f34c50e899c2e4198f3ab56b8a4c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:37:29 +0000
Subject: [PATCH 07/13] feat: align workspace tooling and tests
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
.env.example | 45 ++---
.github/workflows/ci.yml | 14 +-
Dockerfile | 42 +++--
EVODRON.md | 122 ++++++-------
docker-compose.yml | 15 +-
.../packages/api/src/__tests__/api.test.ts | 160 +++++++++++++++++-
evodron/packages/api/src/index.ts | 46 ++++-
evodron/packages/api/src/middleware/auth.ts | 6 +-
evodron/packages/api/tsconfig.json | 3 +
.../packages/cli/src/services/config.test.ts | 55 ++++++
evodron/packages/cli/tsconfig.json | 3 +
evodron/packages/db/package.json | 6 +-
evodron/packages/db/tsconfig.json | 4 +-
evodron/packages/shared/tsconfig.json | 4 +-
package.json | 32 ++--
15 files changed, 422 insertions(+), 135 deletions(-)
create mode 100644 evodron/packages/cli/src/services/config.test.ts
diff --git a/.env.example b/.env.example
index 9cb74ef7..1c66f13b 100644
--- a/.env.example
+++ b/.env.example
@@ -1,29 +1,32 @@
-# Variables d'environnement — Evodron
+# EVODRON repository entrypoint
+#
+# The runnable product now lives in /evodron.
+# Copy this file to .env at the repository root or to evodron/.env.
-# Copier ce fichier en `.env` et remplir les valeurs.
-# Ne jamais committer `.env` dans le dépôt.
+# Secret used to sign JWTs. Use a long random value (32+ chars).
+EVODRON_JWT_SECRET=change-me-to-a-long-random-secret
-# ── Sécurité ──────────────────────────────────────────────────────────────
-# Clé secrète JWT. Utiliser une valeur aléatoire longue (minimum 32 caractères).
-# Exemple : openssl rand -hex 32
-JWT_SECRET=changeme-use-a-long-random-value-here
+# API bind address.
+EVODRON_API_HOST=0.0.0.0
+EVODRON_API_PORT=3000
-# Durée de validité des tokens JWT (défaut : 7d)
-# Formats acceptés : "7d", "24h", "3600s"
-JWT_EXPIRY=7d
+# API URL used by the CLI.
+EVODRON_API_URL=http://localhost:3000
-# ── Serveur ───────────────────────────────────────────────────────────────
-PORT=3000
+# SQLite path for local development.
+EVODRON_DB_URL=file:./evodron.db
-# URL publique de l'application (utilisée pour générer les liens de parrainage)
-# Exemple : https://app.evodron.com
-APP_URL=http://localhost:3000
+# Public base URL used to build referral links.
+EVODRON_REFERRAL_BASE_URL=http://localhost:3000
-# ── Base de données ───────────────────────────────────────────────────────
-# Chemin vers le fichier SQLite (défaut : ./evodron.db)
-# Utiliser :memory: pour les tests uniquement
-DB_PATH=./evodron.db
+# Minimum completed sessions before a referral is rewarded.
+EVODRON_REWARD_MIN_SESSIONS=3
+
+# Optional comma-separated CORS allowlist. Leave unset for development.
+# EVODRON_CORS_ORIGIN=https://app.evodron.io,https://admin.evodron.io
+
+# Max JSON request size in bytes.
+EVODRON_BODY_LIMIT_BYTES=1048576
-# ── Environnement ─────────────────────────────────────────────────────────
-# Valeurs : development | production | test
NODE_ENV=development
+LOG_LEVEL=info
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0f5dd423..eb7dd26c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,11 +21,21 @@ jobs:
cache: npm
- name: Install dependencies
+ working-directory: evodron
run: npm ci
+ - name: Lint workspace
+ working-directory: evodron
+ run: npm run lint
+
- name: Run tests
env:
- JWT_SECRET: test-secret-ci
- DB_PATH: ":memory:"
+ EVODRON_JWT_SECRET: test-secret-ci-secret-ci-secret-ci
+ EVODRON_DB_URL: file:/tmp/evodron-ci.db
NODE_ENV: test
+ working-directory: evodron
run: npm test
+
+ - name: Build workspace
+ working-directory: evodron
+ run: npm run build
diff --git a/Dockerfile b/Dockerfile
index 41adc800..4bee4d1f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,22 +1,42 @@
-FROM node:20-alpine
+FROM node:20-alpine AS builder
-WORKDIR /app
+WORKDIR /app/evodron
+
+COPY evodron/package*.json ./
+COPY evodron/packages/api/package.json ./packages/api/package.json
+COPY evodron/packages/cli/package.json ./packages/cli/package.json
+COPY evodron/packages/db/package.json ./packages/db/package.json
+COPY evodron/packages/shared/package.json ./packages/shared/package.json
+
+RUN npm ci
+
+COPY evodron/ ./
+
+RUN npm run build
+
+FROM node:20-alpine AS runtime
+
+WORKDIR /app/evodron
+
+COPY evodron/package*.json ./
+COPY evodron/packages/api/package.json ./packages/api/package.json
+COPY evodron/packages/cli/package.json ./packages/cli/package.json
+COPY evodron/packages/db/package.json ./packages/db/package.json
+COPY evodron/packages/shared/package.json ./packages/shared/package.json
-# Install dependencies first (layer cache)
-COPY package*.json ./
RUN npm ci --omit=dev
-# Copy application source
-COPY app.js ./
-COPY src/ ./src/
-COPY public/ ./public/
+COPY --from=builder /app/evodron/packages/api/dist ./packages/api/dist
+COPY --from=builder /app/evodron/packages/db/dist ./packages/db/dist
+COPY --from=builder /app/evodron/packages/shared/dist ./packages/shared/dist
-# SQLite database volume mount point
VOLUME ["/data"]
-ENV DB_PATH=/data/evodron.db
+ENV EVODRON_DB_URL=file:/data/evodron.db
+ENV EVODRON_API_HOST=0.0.0.0
+ENV EVODRON_API_PORT=3000
EXPOSE 3000
USER node
-CMD ["node", "app.js"]
+CMD ["sh", "-c", "npm run db:migrate && npm run db:seed && npm run start --workspace=@evodron/api"]
diff --git a/EVODRON.md b/EVODRON.md
index cd5086c7..25815066 100644
--- a/EVODRON.md
+++ b/EVODRON.md
@@ -1,45 +1,27 @@
# Evodron
-**Plateforme de parrainage** — backend Node.js/Express, base SQLite, frontend statique.
+**Plateforme EVODRON** — API TypeScript/Fastify, CLI EVODRON, base SQLite et architecture modulaire.
-> ℹ️ Le fichier `README.md` à la racine documente le **GitHub Copilot CLI** (outil de développement intégré à ce dépôt). Ce fichier `EVODRON.md` documente le **produit EVODRON** lui-même.
+> ℹ️ Le fichier `README.md` à la racine documente le **GitHub Copilot CLI** hérité du dépôt. Le produit EVODRON réellement exécutable vit désormais dans le dossier `/evodron` et est piloté depuis la racine via les scripts npm de ce dépôt.
---
## Architecture
```
-evodron/
-├── app.js # Point d'entrée Express
-├── public/ # Frontend statique (HTML/CSS/JS)
-│ ├── index.html
-│ ├── login.html
-│ ├── register.html
-│ ├── dashboard.html
-│ ├── referral.html
-│ ├── css/style.css
-│ └── js/referral.js
-├── src/
-│ ├── config/
-│ │ └── rewards.js # Configuration des récompenses
-│ ├── db/
-│ │ ├── database.js # Connexion SQLite (better-sqlite3)
-│ │ └── schema.sql # Schéma de la base de données
-│ ├── middleware/
-│ │ ├── auth.js # Vérification JWT
-│ │ └── rateLimiter.js # Rate limiting par IP
-│ ├── models/
-│ │ ├── user.js # Modèle utilisateur
-│ │ ├── referral.js # Modèle parrainage
-│ │ └── reward.js # Modèle récompenses
-│ └── routes/
-│ ├── auth.js # /api/auth (register, login)
-│ ├── health.js # /api/health
-│ └── referral.js # /api/referral (link, stats, rewards, activate-use)
-└── tests/
- ├── referral.test.js # Tests flux de parrainage
- ├── anti-abuse.test.js # Tests anti-fraude
- └── health.test.js # Tests endpoint /api/health
+/
+├── package.json # Scripts racine (setup / build / test / start)
+├── Dockerfile # Image API EVODRON
+├── docker-compose.yml # Déploiement local/simple
+└── evodron/
+ ├── package.json # Workspace npm
+ ├── docs/ # Documentation produit / architecture
+ ├── scripts/setup.sh # Setup développeur
+ └── packages/
+ ├── api/ # API Fastify + auth + referrals + rewards
+ ├── cli/ # CLI EVODRON
+ ├── db/ # Schéma, migrations, seed
+ └── shared/ # Types et schémas partagés
```
## Prérequis
@@ -50,22 +32,19 @@ evodron/
## Installation
```bash
-git clone https://github.com/julesdemangeot-ship-it/EVODRON.git
-cd EVODRON
-npm install
+cd /home/runner/work/EVODRON/EVODRON
cp .env.example .env
-# Éditer .env et définir JWT_SECRET
+# Éditer .env et définir EVODRON_JWT_SECRET
+npm run setup
```
## Démarrage
```bash
-JWT_SECRET=votre-clé-secrète npm start
-# ou avec le fichier .env :
npm start
```
-Le serveur écoute sur `http://localhost:3000` (configurable via `PORT`).
+Le serveur écoute sur `http://localhost:3000` (configurable via `EVODRON_API_PORT`).
## Tests
@@ -73,7 +52,7 @@ Le serveur écoute sur `http://localhost:3000` (configurable via `PORT`).
npm test
```
-Tous les tests utilisent une base SQLite en mémoire (`DB_PATH=:memory:`). Aucune configuration supplémentaire n'est requise.
+La suite lance les tests workspace EVODRON (`evodron/packages/*`).
## API
@@ -81,29 +60,33 @@ Tous les tests utilisent une base SQLite en mémoire (`DB_PATH=:memory:`). Aucun
| Méthode | Endpoint | Description |
|---------|----------|-------------|
-| `POST` | `/api/auth/register` | Créer un compte (avec code de parrainage optionnel) |
-| `POST` | `/api/auth/login` | Se connecter, obtenir un token JWT |
+| `POST` | `/auth/register` | Créer un compte (avec code de parrainage optionnel) |
+| `POST` | `/auth/login` | Se connecter, obtenir access token + refresh token |
+| `POST` | `/auth/refresh` | Renouveler la session |
+| `POST` | `/auth/logout` | Révoquer un refresh token |
### Parrainage
| Méthode | Endpoint | Auth | Description |
|---------|----------|------|-------------|
-| `GET` | `/api/referral/link` | ✅ | Obtenir son lien de parrainage |
-| `GET` | `/api/referral/stats` | ✅ | Statistiques de parrainage |
-| `GET` | `/api/referral/rewards` | ✅ | Historique et récompenses disponibles |
-| `POST` | `/api/referral/claim-reward/:id` | ✅ | Réclamer une récompense |
-| `POST` | `/api/referral/activate-use` | ✅ | Déclarer la première utilisation active |
-| `GET` | `/api/referral/program-info` | ❌ | Conditions du programme (public) |
+| `GET` | `/users/me` | ✅ | Profil courant |
+| `GET` | `/referrals/code` | ✅ | Obtenir son code et lien |
+| `GET` | `/referrals/stats` | ✅ | Statistiques de parrainage |
+| `POST` | `/sessions/start` | ✅ | Démarrer une session CLI |
+| `POST` | `/sessions/end` | ✅ | Terminer une session CLI |
+| `GET` | `/rewards` | ✅ | Historique des crédits |
+| `GET` | `/rewards/rules` | ✅ | Règles actives |
+| `GET` | `/stats` | ✅ | Statistiques d’utilisation |
### Santé
| Méthode | Endpoint | Description |
|---------|----------|-------------|
-| `GET` | `/api/health` | État de l'application et de la base de données |
+| `GET` | `/health` | État de l'application et de la base de données |
### Authentification JWT
-Passer le token JWT via le header HTTP `Authorization` (schéma `Bearer`) ou dans un cookie nommé `token`.
+Passer l’access token JWT via le header HTTP `Authorization: ******
## Variables d'environnement
@@ -111,12 +94,16 @@ Voir `.env.example` pour la liste complète.
| Variable | Obligatoire | Défaut | Description |
|----------|-------------|--------|-------------|
-| `JWT_SECRET` | ✅ | — | Clé secrète JWT |
-| `JWT_EXPIRY` | ❌ | `7d` | Durée de validité du token |
-| `PORT` | ❌ | `3000` | Port d'écoute |
-| `APP_URL` | ❌ | détecté | URL de base pour les liens de parrainage |
-| `DB_PATH` | ❌ | `./evodron.db` | Chemin du fichier SQLite |
+| `EVODRON_JWT_SECRET` | ✅ | — | Clé secrète JWT |
+| `EVODRON_API_PORT` | ❌ | `3000` | Port d'écoute |
+| `EVODRON_API_HOST` | ❌ | `0.0.0.0` | Host d'écoute |
+| `EVODRON_API_URL` | ❌ | `http://localhost:3000` | URL de l’API pour le CLI |
+| `EVODRON_REFERRAL_BASE_URL` | ❌ | `https://evodron.io` | URL de base des liens de parrainage |
+| `EVODRON_DB_URL` | ❌ | `file:./evodron.db` | Chemin/URL de base SQLite |
+| `EVODRON_REWARD_MIN_SESSIONS` | ❌ | `3` | Seuil avant validation d’un parrainage |
+| `EVODRON_BODY_LIMIT_BYTES` | ❌ | `1048576` | Taille max des payloads JSON |
| `NODE_ENV` | ❌ | `development` | Environnement d'exécution |
+| `LOG_LEVEL` | ❌ | `info` | Niveau de logs |
## Déploiement Docker
@@ -130,28 +117,29 @@ docker compose up -d
## Flux de parrainage
```
-Alice s'inscrit → obtient un code de parrainage unique
+Alice crée son compte → obtient un code de parrainage unique
↓
-Alice partage son lien : /register?ref=ABCD1234
+Alice partage son lien : /ref/ABCD1234
↓
-Bob s'inscrit avec ce lien → reçoit un bonus de bienvenue (10 crédits)
+Bob s'inscrit avec ce code → reçoit un bonus de bienvenue (50 crédits)
↓
-Bob effectue sa première action active → POST /api/referral/activate-use
+Bob complète le nombre minimum de sessions configuré
↓
-Alice reçoit sa récompense de parrain (20 crédits)
+Alice reçoit sa récompense de parrain (100 crédits par défaut)
```
## Sécurité
- Mots de passe hachés avec **bcrypt** (coût 12)
-- Tokens JWT signés (HS256)
-- Rate limiting : 10 req/15 min sur `/api/auth`, 100 req/min sur `/api/referral`
-- Auto-parrainage interdit (vérification modèle + contrainte DB)
-- Un utilisateur ne peut avoir qu'un seul parrain (contrainte UNIQUE en base)
-- Pas de récompense sans activation effective du filleul
+- Access tokens courts + refresh tokens révoquables
+- Rate limiting global et spécifique auth
+- Auto-parrainage interdit
+- Un utilisateur ne peut avoir qu'un seul parrain
+- IP hachées pour l’anti-abus
+- Pas de récompense sans usage vérifié
## Licence
-Le code source EVODRON (dossiers `src/`, `public/`, `tests/`, fichiers `app.js`, `package.json`) est propriétaire.
+Le code source EVODRON exécutable se trouve dans `evodron/` et est propriétaire.
Le fichier `README.md`, `install.sh`, `changelog.md` et `LICENSE.md` sont des fichiers hérités du **GitHub Copilot CLI** distribués sous leur propre licence (voir `LICENSE.md`).
diff --git a/docker-compose.yml b/docker-compose.yml
index 9636c96d..b5a0a093 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,18 +1,23 @@
services:
- app:
+ api:
build: .
ports:
- "3000:3000"
environment:
- - JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required}
- - JWT_EXPIRY=${JWT_EXPIRY:-7d}
- - APP_URL=${APP_URL:-http://localhost:3000}
+ - EVODRON_JWT_SECRET=${EVODRON_JWT_SECRET:?EVODRON_JWT_SECRET is required}
+ - EVODRON_API_HOST=0.0.0.0
+ - EVODRON_API_PORT=3000
+ - EVODRON_DB_URL=file:/data/evodron.db
+ - EVODRON_API_URL=${EVODRON_API_URL:-http://localhost:3000}
+ - EVODRON_REFERRAL_BASE_URL=${EVODRON_REFERRAL_BASE_URL:-http://localhost:3000}
+ - EVODRON_REWARD_MIN_SESSIONS=${EVODRON_REWARD_MIN_SESSIONS:-3}
- NODE_ENV=${NODE_ENV:-production}
+ - LOG_LEVEL=${LOG_LEVEL:-info}
volumes:
- evodron_data:/data
restart: unless-stopped
healthcheck:
- test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
+ test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
diff --git a/evodron/packages/api/src/__tests__/api.test.ts b/evodron/packages/api/src/__tests__/api.test.ts
index 5dcaf7b2..d84d0e05 100644
--- a/evodron/packages/api/src/__tests__/api.test.ts
+++ b/evodron/packages/api/src/__tests__/api.test.ts
@@ -4,6 +4,8 @@ import type { FastifyInstance } from 'fastify';
import os from 'os';
import path from 'path';
import fs from 'fs';
+import { getDb, schema } from '@evodron/db';
+import { eq } from 'drizzle-orm';
let app: FastifyInstance;
@@ -12,7 +14,6 @@ const testDbPath = path.join(os.tmpdir(), `evodron-test-${Date.now()}.db`);
// Set up required env before building app
process.env['EVODRON_JWT_SECRET'] = 'test-secret-that-is-long-enough-32chars!!';
-process.env['EVODRON_REFRESH_SECRET'] = 'test-refresh-secret-that-is-long-32chars!!';
process.env['EVODRON_DB_URL'] = `file:${testDbPath}`;
beforeAll(async () => {
@@ -57,6 +58,8 @@ describe('Health check', () => {
const body = res.json();
expect(body.status).toBe('ok');
expect(body.service).toBe('evodron-api');
+ expect(body.db).toBe('ok');
+ expect(body.version).toBeDefined();
});
});
@@ -107,6 +110,55 @@ describe('Auth — register and login', () => {
});
expect(res.statusCode).toBe(401);
});
+
+ it('POST /auth/refresh rotates refresh tokens', async () => {
+ const loginRes = await app.inject({
+ method: 'POST',
+ url: '/auth/login',
+ payload: { email, password },
+ });
+ const firstRefreshToken = loginRes.json().data.refreshToken as string;
+
+ const refreshRes = await app.inject({
+ method: 'POST',
+ url: '/auth/refresh',
+ payload: { refreshToken: firstRefreshToken },
+ });
+ expect(refreshRes.statusCode).toBe(200);
+ const rotatedRefreshToken = refreshRes.json().data.refreshToken as string;
+ expect(rotatedRefreshToken).toBeDefined();
+ expect(rotatedRefreshToken).not.toBe(firstRefreshToken);
+
+ const reusedOldTokenRes = await app.inject({
+ method: 'POST',
+ url: '/auth/refresh',
+ payload: { refreshToken: firstRefreshToken },
+ });
+ expect(reusedOldTokenRes.statusCode).toBe(401);
+ });
+
+ it('POST /auth/logout revokes refresh tokens', async () => {
+ const loginRes = await app.inject({
+ method: 'POST',
+ url: '/auth/login',
+ payload: { email, password },
+ });
+ const refreshToken = loginRes.json().data.refreshToken as string;
+
+ const logoutRes = await app.inject({
+ method: 'POST',
+ url: '/auth/logout',
+ payload: { refreshToken },
+ });
+ expect(logoutRes.statusCode).toBe(200);
+
+ const refreshRes = await app.inject({
+ method: 'POST',
+ url: '/auth/refresh',
+ payload: { refreshToken },
+ });
+ expect(refreshRes.statusCode).toBe(401);
+ });
});
describe('Users — /users/me', () => {
@@ -213,6 +265,49 @@ describe('Referral system', () => {
expect(res.statusCode).toBe(400);
expect(res.json().code).toBe('INVALID_REFERRAL');
});
+
+ it('Referrer receives credits after referee completes the activation threshold', async () => {
+ const registerReferee = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `threshold-${Date.now()}@example.com`,
+ username: `threshold${Date.now()}`,
+ password: 'StrongPass123!',
+ referralCode,
+ },
+ });
+ const refereeToken = registerReferee.json().data.accessToken as string;
+
+ for (let i = 0; i < 3; i++) {
+ const startRes = await app.inject({
+ method: 'POST',
+ url: '/sessions/start',
+ headers: { authorization: 'Bearer ' + refereeToken },
+ payload: { clientVersion: '0.1.0' },
+ });
+ expect(startRes.statusCode).toBe(201);
+
+ const sessionId = startRes.json().data.sessionId as string;
+ const endRes = await app.inject({
+ method: 'POST',
+ url: '/sessions/end',
+ headers: { authorization: 'Bearer ' + refereeToken },
+ payload: { sessionId, commandsCount: i + 1 },
+ });
+ expect(endRes.statusCode).toBe(200);
+ }
+
+ const rewardsRes = await app.inject({
+ method: 'GET',
+ url: '/rewards',
+ headers: { authorization: 'Bearer ' + referrerToken },
+ });
+ expect(rewardsRes.statusCode).toBe(200);
+ expect(
+ rewardsRes.json().data.rewards.some((reward: { type: string }) => reward.type === 'referral_active'),
+ ).toBe(true);
+ });
});
describe('Sessions', () => {
@@ -312,3 +407,66 @@ describe('Stats', () => {
expect(body.data.totalSessions).toBe(0);
});
});
+
+describe('Admin access control', () => {
+ it('rejects non-admin users', async () => {
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email: `admin-block-${Date.now()}@example.com`,
+ username: `adminblock${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+
+ const token = reg.json().data.accessToken as string;
+ const res = await app.inject({
+ method: 'GET',
+ url: '/admin/abuse-flags',
+ headers: { authorization: 'Bearer ' + token },
+ });
+
+ expect(res.statusCode).toBe(403);
+ });
+
+ it('allows admin users to inspect abuse flags', async () => {
+ const email = `admin-${Date.now()}@example.com`;
+ const reg = await app.inject({
+ method: 'POST',
+ url: '/auth/register',
+ payload: {
+ email,
+ username: `admin${Date.now()}`,
+ password: 'StrongPass123!',
+ },
+ });
+
+ const userId = reg.json().data.userId as string;
+ await getDb()
+ .update(schema.users)
+ .set({ isAdmin: true, updatedAt: new Date().toISOString() })
+ .where(eq(schema.users.id, userId));
+
+ const loginRes = await app.inject({
+ method: 'POST',
+ url: '/auth/login',
+ payload: {
+ email,
+ password: 'StrongPass123!',
+ },
+ });
+
+ expect(loginRes.statusCode).toBe(200);
+ const accessToken = loginRes.json().data.accessToken as string;
+
+ const res = await app.inject({
+ method: 'GET',
+ url: '/admin/abuse-flags',
+ headers: { authorization: 'Bearer ' + accessToken },
+ });
+
+ expect(res.statusCode).toBe(200);
+ expect(Array.isArray(res.json().data.flags)).toBe(true);
+ });
+});
diff --git a/evodron/packages/api/src/index.ts b/evodron/packages/api/src/index.ts
index a2dce2bb..eb078e5f 100644
--- a/evodron/packages/api/src/index.ts
+++ b/evodron/packages/api/src/index.ts
@@ -11,10 +11,11 @@ import { referralRoutes } from './routes/referrals';
import { rewardRoutes } from './routes/rewards';
import { statsRoutes } from './routes/stats';
import { adminRoutes } from './routes/admin';
-import { getDb } from '@evodron/db';
+import { getDb, schema } from '@evodron/db';
const PORT = parseInt(process.env['EVODRON_API_PORT'] ?? '3000', 10);
const HOST = process.env['EVODRON_API_HOST'] ?? '0.0.0.0';
+const BODY_LIMIT = parseInt(process.env['EVODRON_BODY_LIMIT_BYTES'] ?? '1048576', 10);
export async function buildApp() {
const app = Fastify({
@@ -22,12 +23,18 @@ export async function buildApp() {
level: process.env['LOG_LEVEL'] ?? 'info',
},
trustProxy: true,
+ bodyLimit: BODY_LIMIT,
});
// ── Plugins ──────────────────────────────────────────────────────────────
+ const corsOrigin = process.env['EVODRON_CORS_ORIGIN'];
+ const allowedOrigins = corsOrigin
+ ? corsOrigin.split(',').map((origin) => origin.trim()).filter(Boolean)
+ : null;
+
await app.register(cors, {
- origin: true,
+ origin: allowedOrigins ?? true,
credentials: true,
});
@@ -68,7 +75,40 @@ export async function buildApp() {
// ── Health check ─────────────────────────────────────────────────────────
- app.get('/health', async () => ({ status: 'ok', service: 'evodron-api' }));
+ app.get('/health', async (_request, reply) => {
+ const status = {
+ status: 'ok',
+ service: 'evodron-api',
+ version: process.env['npm_package_version'] ?? '0.1.0',
+ db: 'ok',
+ timestamp: new Date().toISOString(),
+ };
+
+ try {
+ await db.select({ id: schema.users.id }).from(schema.users).limit(1).all();
+ } catch {
+ status.status = 'degraded';
+ status.db = 'error';
+ }
+
+ return reply.code(status.status === 'ok' ? 200 : 503).send(status);
+ });
+
+ app.setNotFoundHandler((_request, reply) => {
+ return reply.code(404).send({ success: false, error: 'Route not found', code: 'NOT_FOUND' });
+ });
+
+ app.setErrorHandler((error, _request, reply) => {
+ app.log.error(error);
+
+ if (reply.sent) return;
+
+ if ((error as { validation?: unknown }).validation) {
+ return reply.code(400).send({ success: false, error: 'Invalid input', code: 'VALIDATION_ERROR' });
+ }
+
+ return reply.code(500).send({ success: false, error: 'Internal server error', code: 'INTERNAL_ERROR' });
+ });
return app;
}
diff --git a/evodron/packages/api/src/middleware/auth.ts b/evodron/packages/api/src/middleware/auth.ts
index 9bc35b7d..b540ad6a 100644
--- a/evodron/packages/api/src/middleware/auth.ts
+++ b/evodron/packages/api/src/middleware/auth.ts
@@ -7,7 +7,7 @@ export async function authenticate(
try {
await request.jwtVerify();
} catch {
- reply.code(401).send({ success: false, error: 'Unauthorized', code: 'UNAUTHORIZED' });
+ return reply.code(401).send({ success: false, error: 'Unauthorized', code: 'UNAUTHORIZED' });
}
}
@@ -19,9 +19,9 @@ export async function authenticateAdmin(
await request.jwtVerify();
const payload = request.user as { isAdmin?: boolean };
if (!payload.isAdmin) {
- reply.code(403).send({ success: false, error: 'Forbidden', code: 'FORBIDDEN' });
+ return reply.code(403).send({ success: false, error: 'Forbidden', code: 'FORBIDDEN' });
}
} catch {
- reply.code(401).send({ success: false, error: 'Unauthorized', code: 'UNAUTHORIZED' });
+ return reply.code(401).send({ success: false, error: 'Unauthorized', code: 'UNAUTHORIZED' });
}
}
diff --git a/evodron/packages/api/tsconfig.json b/evodron/packages/api/tsconfig.json
index 18803392..d4542000 100644
--- a/evodron/packages/api/tsconfig.json
+++ b/evodron/packages/api/tsconfig.json
@@ -2,13 +2,16 @@
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
+ "moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
"rootDir": "src",
+ "baseUrl": ".",
"strict": true,
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
+ "types": ["node"],
"paths": {
"@evodron/shared": ["../shared/src"],
"@evodron/db": ["../db/src"]
diff --git a/evodron/packages/cli/src/services/config.test.ts b/evodron/packages/cli/src/services/config.test.ts
new file mode 100644
index 00000000..e2d85f35
--- /dev/null
+++ b/evodron/packages/cli/src/services/config.test.ts
@@ -0,0 +1,55 @@
+import { afterEach, describe, expect, it } from 'vitest';
+import fs from 'fs';
+import os from 'os';
+import path from 'path';
+import { clearConfig, getApiUrl, loadConfig, saveConfig } from './config';
+
+function createTempConfigDir(): string {
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'evodron-cli-config-'));
+}
+
+describe('CLI config service', () => {
+ afterEach(() => {
+ delete process.env['EVODRON_CONFIG_DIR'];
+ delete process.env['EVODRON_API_URL'];
+ });
+
+ it('saves and loads credentials from the configured directory', () => {
+ const dir = createTempConfigDir();
+ process.env['EVODRON_CONFIG_DIR'] = dir;
+
+ saveConfig({
+ accessToken: 'access-token',
+ refreshToken: 'refresh-token',
+ username: 'alice',
+ userId: 'user-1',
+ });
+
+ expect(loadConfig()).toEqual({
+ accessToken: 'access-token',
+ refreshToken: 'refresh-token',
+ username: 'alice',
+ userId: 'user-1',
+ });
+ });
+
+ it('prefers the saved API URL over the environment fallback', () => {
+ const dir = createTempConfigDir();
+ process.env['EVODRON_CONFIG_DIR'] = dir;
+ process.env['EVODRON_API_URL'] = 'http://env.example.test';
+
+ saveConfig({ apiUrl: 'http://saved.example.test' });
+
+ expect(getApiUrl()).toBe('http://saved.example.test');
+ });
+
+ it('clears the persisted config file', () => {
+ const dir = createTempConfigDir();
+ process.env['EVODRON_CONFIG_DIR'] = dir;
+
+ saveConfig({ accessToken: 'token' });
+ clearConfig();
+
+ expect(loadConfig()).toEqual({});
+ });
+});
diff --git a/evodron/packages/cli/tsconfig.json b/evodron/packages/cli/tsconfig.json
index 572b9fe3..d8ab8ee9 100644
--- a/evodron/packages/cli/tsconfig.json
+++ b/evodron/packages/cli/tsconfig.json
@@ -2,13 +2,16 @@
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
+ "moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
"rootDir": "src",
+ "baseUrl": ".",
"strict": true,
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
+ "types": ["node"],
"paths": {
"@evodron/shared": ["../shared/src"]
}
diff --git a/evodron/packages/db/package.json b/evodron/packages/db/package.json
index 2b775c63..7a065954 100644
--- a/evodron/packages/db/package.json
+++ b/evodron/packages/db/package.json
@@ -6,8 +6,10 @@
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
- "migrate": "tsx src/migrate.ts",
- "seed": "tsx src/seed.ts"
+ "migrate": "node dist/migrate.js",
+ "seed": "node dist/seed.js",
+ "dev:migrate": "tsx src/migrate.ts",
+ "dev:seed": "tsx src/seed.ts"
},
"dependencies": {
"better-sqlite3": "^9.4.3",
diff --git a/evodron/packages/db/tsconfig.json b/evodron/packages/db/tsconfig.json
index 0b66e711..9e7b1246 100644
--- a/evodron/packages/db/tsconfig.json
+++ b/evodron/packages/db/tsconfig.json
@@ -2,6 +2,7 @@
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
+ "moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
"rootDir": "src",
@@ -9,7 +10,8 @@
"esModuleInterop": true,
"declaration": true,
"declarationMap": true,
- "sourceMap": true
+ "sourceMap": true,
+ "types": ["node"]
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/evodron/packages/shared/tsconfig.json b/evodron/packages/shared/tsconfig.json
index 0b66e711..9e7b1246 100644
--- a/evodron/packages/shared/tsconfig.json
+++ b/evodron/packages/shared/tsconfig.json
@@ -2,6 +2,7 @@
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
+ "moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
"rootDir": "src",
@@ -9,7 +10,8 @@
"esModuleInterop": true,
"declaration": true,
"declarationMap": true,
- "sourceMap": true
+ "sourceMap": true,
+ "types": ["node"]
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/package.json b/package.json
index 4cd7e24d..e22a8b71 100644
--- a/package.json
+++ b/package.json
@@ -1,24 +1,20 @@
{
- "name": "evodron",
+ "name": "evodron-repository",
"version": "1.0.0",
- "description": "Evodron — Plateforme de parrainage (backend Node.js/Express + SQLite)",
- "main": "app.js",
+ "description": "Repository entrypoint for the EVODRON platform workspace",
+ "private": true,
"scripts": {
- "start": "node app.js",
- "dev": "node app.js",
- "test": "jest --testPathPattern=tests/"
+ "setup": "cd evodron && npm ci && npm run build && npm run db:migrate && npm run db:seed",
+ "build": "cd evodron && npm run build",
+ "test": "cd evodron && npm test",
+ "lint": "cd evodron && npm run lint",
+ "dev:api": "cd evodron && npm run dev:api",
+ "dev:cli": "cd evodron && npm run dev:cli",
+ "db:migrate": "cd evodron && npm run db:migrate",
+ "db:seed": "cd evodron && npm run db:seed",
+ "start": "cd evodron && npm run start --workspace=@evodron/api"
},
- "dependencies": {
- "bcryptjs": "^2.4.3",
- "better-sqlite3": "^9.4.3",
- "cookie-parser": "^1.4.6",
- "express": "^4.18.2",
- "express-rate-limit": "^8.6.2",
- "jsonwebtoken": "^9.0.2",
- "nanoid": "^3.3.7"
- },
- "devDependencies": {
- "jest": "^29.7.0",
- "supertest": "^6.3.4"
+ "engines": {
+ "node": ">=18.0.0"
}
}
From 5e4e5780bfc8e424f9ded3c89ba63c954b47db85 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:42:21 +0000
Subject: [PATCH 08/13] feat: harden workspace api and cli
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
evodron/package-lock.json | 73 +-
evodron/package.json | 2 +-
evodron/packages/api/package.json | 2 +-
.../packages/api/src/__tests__/api.test.ts | 4 +
evodron/packages/api/src/routes/admin.ts | 12 +-
evodron/packages/api/tsconfig.json | 8 +-
evodron/packages/cli/package.json | 4 +-
evodron/packages/cli/tsconfig.json | 7 +-
evodron/packages/cli/vitest.config.mts | 16 +
evodron/packages/db/src/schema.d.ts | 2 +-
evodron/packages/db/src/schema.ts | 4 +-
evodron/packages/db/tsconfig.json | 5 +-
evodron/packages/shared/tsconfig.json | 5 +-
package-lock.json | 5350 +----------------
14 files changed, 118 insertions(+), 5376 deletions(-)
create mode 100644 evodron/packages/cli/vitest.config.mts
diff --git a/evodron/package-lock.json b/evodron/package-lock.json
index 89230443..f1b58de1 100644
--- a/evodron/package-lock.json
+++ b/evodron/package-lock.json
@@ -1601,6 +1601,21 @@
],
"license": "BSD-3-Clause"
},
+ "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/asn1.js": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
@@ -1790,6 +1805,7 @@
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
"integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
@@ -1821,6 +1837,24 @@
"node": ">=0.10"
}
},
+ "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/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/commander": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
@@ -2702,6 +2736,15 @@
"sisteransi": "^1.0.5"
}
},
+ "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/heap": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
@@ -3907,6 +3950,18 @@
"node": ">=16"
}
},
+ "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/tar-fs": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
@@ -5248,7 +5303,7 @@
"version": "0.1.0",
"dependencies": {
"@evodron/shared": "*",
- "chalk": "^5.3.0",
+ "chalk": "^4.1.2",
"commander": "^12.0.0",
"dotenv": "^16.4.5",
"node-fetch": "^3.3.2"
@@ -5263,6 +5318,22 @@
"vitest": "^4.1.10"
}
},
+ "packages/cli/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"
+ }
+ },
"packages/db": {
"name": "@evodron/db",
"version": "0.1.0",
diff --git a/evodron/package.json b/evodron/package.json
index 073e936c..e43c52b0 100644
--- a/evodron/package.json
+++ b/evodron/package.json
@@ -7,7 +7,7 @@
"packages/*"
],
"scripts": {
- "build": "npm run build --workspaces",
+ "build": "npm run build --workspace=@evodron/shared && npm run build --workspace=@evodron/db && npm run build --workspace=@evodron/api && npm run build --workspace=@evodron/cli",
"test": "npm run test --workspaces --if-present",
"lint": "npm run lint --workspaces --if-present",
"dev:api": "npm run dev --workspace=packages/api",
diff --git a/evodron/packages/api/package.json b/evodron/packages/api/package.json
index 91332a5b..072133bc 100644
--- a/evodron/packages/api/package.json
+++ b/evodron/packages/api/package.json
@@ -7,7 +7,7 @@
"build": "tsc",
"dev": "tsx watch src/index.ts",
"start": "node dist/index.js",
- "test": "vitest run",
+ "test": "vitest run src",
"lint": "tsc --noEmit"
},
"dependencies": {
diff --git a/evodron/packages/api/src/__tests__/api.test.ts b/evodron/packages/api/src/__tests__/api.test.ts
index d84d0e05..6ed1d4a4 100644
--- a/evodron/packages/api/src/__tests__/api.test.ts
+++ b/evodron/packages/api/src/__tests__/api.test.ts
@@ -32,6 +32,10 @@ beforeAll(async () => {
`CREATE TABLE IF NOT EXISTS abuse_flags (id TEXT PRIMARY KEY, user_id TEXT NOT NULL, reason TEXT NOT NULL, detail TEXT, resolved_at TEXT, flagged_at TEXT NOT NULL)`,
`CREATE TABLE IF NOT EXISTS ip_registry (id TEXT PRIMARY KEY, ip_hash TEXT NOT NULL, user_id TEXT NOT NULL, seen_at TEXT NOT NULL)`,
`CREATE TABLE IF NOT EXISTS refresh_tokens (id TEXT PRIMARY KEY, user_id TEXT NOT NULL, token_hash TEXT NOT NULL UNIQUE, expires_at TEXT NOT NULL, created_at TEXT NOT NULL, revoked_at TEXT)`,
+ `INSERT OR IGNORE INTO reward_rules (id, name, trigger, credits, active, description, updated_at) VALUES
+ ('rule-referrer', 'referral_active_referrer', 'referral_active', 100, 1, 'Credits awarded to the referrer when a referee reaches active status', '${new Date().toISOString()}'),
+ ('rule-onboarding', 'referral_onboarding_referee', 'referral_onboarding', 50, 1, 'Onboarding credits awarded to a referred user', '${new Date().toISOString()}'),
+ ('rule-milestone', 'milestone_10_sessions', 'milestone_10_sessions', 25, 1, 'Bonus credits for completing 10 sessions', '${new Date().toISOString()}')`,
];
db.transaction(() => {
diff --git a/evodron/packages/api/src/routes/admin.ts b/evodron/packages/api/src/routes/admin.ts
index 045c1789..f3b66be6 100644
--- a/evodron/packages/api/src/routes/admin.ts
+++ b/evodron/packages/api/src/routes/admin.ts
@@ -29,8 +29,8 @@ export async function adminRoutes(app: FastifyInstance) {
app.post(
'/abuse-flags/:id/resolve',
{ preHandler: [authenticateAdmin] },
- async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
- const { id } = req.params;
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { id } = req.params as { id: string };
await db
.update(schema.abuseFlags)
@@ -46,8 +46,8 @@ export async function adminRoutes(app: FastifyInstance) {
app.post(
'/users/:id/ban',
{ preHandler: [authenticateAdmin] },
- async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
- const { id } = req.params;
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { id } = req.params as { id: string };
const timestamp = now();
await db
@@ -83,8 +83,8 @@ export async function adminRoutes(app: FastifyInstance) {
app.patch(
'/reward-rules/:id',
{ preHandler: [authenticateAdmin] },
- async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
- const { id } = req.params;
+ async (req: FastifyRequest, reply: FastifyReply) => {
+ const { id } = req.params as { id: string };
const body = req.body as { credits?: number; active?: boolean; description?: string };
const timestamp = now();
diff --git a/evodron/packages/api/tsconfig.json b/evodron/packages/api/tsconfig.json
index d4542000..b224f046 100644
--- a/evodron/packages/api/tsconfig.json
+++ b/evodron/packages/api/tsconfig.json
@@ -1,21 +1,17 @@
{
"compilerOptions": {
"target": "ES2020",
- "module": "commonjs",
+ "module": "Node16",
"moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
"rootDir": "src",
- "baseUrl": ".",
"strict": true,
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
"types": ["node"],
- "paths": {
- "@evodron/shared": ["../shared/src"],
- "@evodron/db": ["../db/src"]
- }
+ "skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/evodron/packages/cli/package.json b/evodron/packages/cli/package.json
index 957c5c82..ca5bf145 100644
--- a/evodron/packages/cli/package.json
+++ b/evodron/packages/cli/package.json
@@ -10,12 +10,12 @@
"build": "tsc",
"dev": "tsx watch src/bin/evodron.ts",
"start": "node dist/bin/evodron.js",
- "test": "vitest run",
+ "test": "vitest run src",
"lint": "tsc --noEmit"
},
"dependencies": {
"@evodron/shared": "*",
- "chalk": "^5.3.0",
+ "chalk": "^4.1.2",
"commander": "^12.0.0",
"dotenv": "^16.4.5",
"node-fetch": "^3.3.2"
diff --git a/evodron/packages/cli/tsconfig.json b/evodron/packages/cli/tsconfig.json
index d8ab8ee9..b224f046 100644
--- a/evodron/packages/cli/tsconfig.json
+++ b/evodron/packages/cli/tsconfig.json
@@ -1,20 +1,17 @@
{
"compilerOptions": {
"target": "ES2020",
- "module": "commonjs",
+ "module": "Node16",
"moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
"rootDir": "src",
- "baseUrl": ".",
"strict": true,
"esModuleInterop": true,
"declaration": true,
"sourceMap": true,
"types": ["node"],
- "paths": {
- "@evodron/shared": ["../shared/src"]
- }
+ "skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/evodron/packages/cli/vitest.config.mts b/evodron/packages/cli/vitest.config.mts
new file mode 100644
index 00000000..aae509c1
--- /dev/null
+++ b/evodron/packages/cli/vitest.config.mts
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vitest/config';
+
+export default defineConfig({
+ resolve: {
+ alias: {
+ '@evodron/shared': import.meta.dirname + '/../shared/src/index.ts',
+ },
+ },
+ test: {
+ environment: 'node',
+ globals: false,
+ testTimeout: 30000,
+ include: ['src/**/*.test.ts'],
+ exclude: ['dist/**', 'node_modules/**'],
+ },
+});
diff --git a/evodron/packages/db/src/schema.d.ts b/evodron/packages/db/src/schema.d.ts
index f5c81e97..a81404b2 100644
--- a/evodron/packages/db/src/schema.d.ts
+++ b/evodron/packages/db/src/schema.d.ts
@@ -324,7 +324,7 @@ export declare const rewards: import("drizzle-orm/sqlite-core").SQLiteTableWithC
tableName: "rewards";
dataType: "string";
columnType: "SQLiteText";
- data: "manual" | "referral_active" | "referral_onboarding" | "milestone";
+ data: "referral_active" | "referral_onboarding" | "milestone" | "manual";
driverParam: string;
notNull: true;
hasDefault: false;
diff --git a/evodron/packages/db/src/schema.ts b/evodron/packages/db/src/schema.ts
index 0dbffbb9..b727553b 100644
--- a/evodron/packages/db/src/schema.ts
+++ b/evodron/packages/db/src/schema.ts
@@ -1,4 +1,4 @@
-import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core';
+import { sqliteTable, text, integer, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';
// ─── users ────────────────────────────────────────────────────────────────────
@@ -8,7 +8,7 @@ export const users = sqliteTable('users', {
username: text('username').notNull().unique(),
passwordHash: text('password_hash').notNull(),
referralCode: text('referral_code').notNull().unique(),
- referredBy: text('referred_by').references(() => users.id),
+ referredBy: text('referred_by').references((): AnySQLiteColumn => users.id),
credits: integer('credits').notNull().default(0),
level: text('level', { enum: ['bronze', 'silver', 'gold'] }).notNull().default('bronze'),
isAdmin: integer('is_admin', { mode: 'boolean' }).notNull().default(false),
diff --git a/evodron/packages/db/tsconfig.json b/evodron/packages/db/tsconfig.json
index 9e7b1246..53d4e1af 100644
--- a/evodron/packages/db/tsconfig.json
+++ b/evodron/packages/db/tsconfig.json
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "ES2020",
- "module": "commonjs",
+ "module": "Node16",
"moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
@@ -11,7 +11,8 @@
"declaration": true,
"declarationMap": true,
"sourceMap": true,
- "types": ["node"]
+ "types": ["node"],
+ "skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/evodron/packages/shared/tsconfig.json b/evodron/packages/shared/tsconfig.json
index 9e7b1246..53d4e1af 100644
--- a/evodron/packages/shared/tsconfig.json
+++ b/evodron/packages/shared/tsconfig.json
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "ES2020",
- "module": "commonjs",
+ "module": "Node16",
"moduleResolution": "node16",
"lib": ["ES2020"],
"outDir": "dist",
@@ -11,7 +11,8 @@
"declaration": true,
"declarationMap": true,
"sourceMap": true,
- "types": ["node"]
+ "types": ["node"],
+ "skipLibCheck": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/package-lock.json b/package-lock.json
index 69b68ae0..612c4255 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5358 +1,14 @@
{
- "name": "evodron",
+ "name": "evodron-repository",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "evodron",
+ "name": "evodron-repository",
"version": "1.0.0",
- "dependencies": {
- "bcryptjs": "^2.4.3",
- "better-sqlite3": "^9.4.3",
- "cookie-parser": "^1.4.6",
- "express": "^4.18.2",
- "express-rate-limit": "^8.6.2",
- "jsonwebtoken": "^9.0.2",
- "nanoid": "^3.3.7"
- },
- "devDependencies": {
- "jest": "^29.7.0",
- "supertest": "^6.3.4"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
- "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.29.7",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
- "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
- "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/generator": "^7.29.7",
- "@babel/helper-compilation-targets": "^7.29.7",
- "@babel/helper-module-transforms": "^7.29.7",
- "@babel/helpers": "^7.29.7",
- "@babel/parser": "^7.29.7",
- "@babel/template": "^7.29.7",
- "@babel/traverse": "^7.29.7",
- "@babel/types": "^7.29.7",
- "@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/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/@babel/core/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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@babel/generator": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
- "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.8",
- "@babel/types": "^7.29.8",
- "@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-compilation-targets": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
- "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.29.7",
- "@babel/helper-validator-option": "^7.29.7",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
- "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
- "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
- "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.29.7",
- "@babel/helper-validator-identifier": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
- "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
- "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
- "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
- "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
- "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
- "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.8"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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-import-attributes": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz",
- "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
- "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
- "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
- "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/parser": "^7.29.7",
- "@babel/types": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz",
- "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.7",
- "@babel/generator": "^7.29.8",
- "@babel/helper-globals": "^7.29.7",
- "@babel/parser": "^7.29.8",
- "@babel/template": "^7.29.7",
- "@babel/types": "^7.29.8",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/@babel/traverse/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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@babel/types": {
- "version": "7.29.8",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
- "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.29.7",
- "@babel/helper-validator-identifier": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@bcoe/v8-coverage": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
- "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@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==",
- "dev": true,
- "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/schema": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz",
- "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@jest/console": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
- "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "jest-message-util": "^29.7.0",
- "jest-util": "^29.7.0",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/core": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
- "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/console": "^29.7.0",
- "@jest/reporters": "^29.7.0",
- "@jest/test-result": "^29.7.0",
- "@jest/transform": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.0.0",
- "ci-info": "^3.2.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "jest-changed-files": "^29.7.0",
- "jest-config": "^29.7.0",
- "jest-haste-map": "^29.7.0",
- "jest-message-util": "^29.7.0",
- "jest-regex-util": "^29.6.3",
- "jest-resolve": "^29.7.0",
- "jest-resolve-dependencies": "^29.7.0",
- "jest-runner": "^29.7.0",
- "jest-runtime": "^29.7.0",
- "jest-snapshot": "^29.7.0",
- "jest-util": "^29.7.0",
- "jest-validate": "^29.7.0",
- "jest-watcher": "^29.7.0",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.7.0",
- "slash": "^3.0.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "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==",
- "dev": true,
- "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/expect": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
- "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "expect": "^29.7.0",
- "jest-snapshot": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/expect-utils": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
- "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jest-get-type": "^29.6.3"
- },
- "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==",
- "dev": true,
- "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/globals": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
- "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "^29.7.0",
- "@jest/expect": "^29.7.0",
- "@jest/types": "^29.6.3",
- "jest-mock": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/reporters": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
- "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.7.0",
- "@jest/test-result": "^29.7.0",
- "@jest/transform": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@jridgewell/trace-mapping": "^0.3.18",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "collect-v8-coverage": "^1.0.0",
- "exit": "^0.1.2",
- "glob": "^7.1.3",
- "graceful-fs": "^4.2.9",
- "istanbul-lib-coverage": "^3.0.0",
- "istanbul-lib-instrument": "^6.0.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^4.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "^29.7.0",
- "jest-util": "^29.7.0",
- "jest-worker": "^29.7.0",
- "slash": "^3.0.0",
- "string-length": "^4.0.1",
- "strip-ansi": "^6.0.0",
- "v8-to-istanbul": "^9.0.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/source-map": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
- "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.18",
- "callsites": "^3.0.0",
- "graceful-fs": "^4.2.9"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/test-result": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
- "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/console": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "collect-v8-coverage": "^1.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/test-sequencer": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
- "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/test-result": "^29.7.0",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.7.0",
- "slash": "^3.0.0"
- },
- "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==",
- "dev": true,
- "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/types": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
- "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
- "dev": true,
- "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/@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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@paralleldrive/cuid2": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
- "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@noble/hashes": "^1.1.5"
- }
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.27.12",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz",
- "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "node_modules/@types/node": {
- "version": "26.2.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
- "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~8.3.0"
- }
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT"
- },
- "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/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.21.3"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "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/asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/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==",
- "dev": true,
- "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-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==",
- "dev": true,
- "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-istanbul/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==",
- "dev": true,
- "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/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==",
- "dev": true,
- "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-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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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.11.13",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz",
- "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/bcryptjs": {
- "version": "2.4.3",
- "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
- "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
- "license": "MIT"
- },
- "node_modules/better-sqlite3": {
- "version": "9.6.0",
- "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.6.0.tgz",
- "integrity": "sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "bindings": "^1.5.0",
- "prebuild-install": "^7.1.1"
- }
- },
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "license": "MIT",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/body-parser": {
- "version": "1.20.6",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz",
- "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==",
- "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.15.1",
- "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/brace-expansion": {
- "version": "1.1.18",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
- "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.28.8",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz",
- "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==",
- "dev": true,
- "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": {
- "baseline-browser-mapping": "^2.11.12",
- "caniuse-lite": "^1.0.30001809",
- "electron-to-chromium": "^1.5.402",
- "node-releases": "^2.0.53",
- "update-browserslist-db": "^1.3.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==",
- "dev": true,
- "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-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "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==",
- "dev": true,
- "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/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/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001809",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz",
- "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==",
- "dev": true,
- "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": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/char-regex": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
- "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "license": "ISC"
- },
- "node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cjs-module-lexer": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
- "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
- "dev": true,
- "license": "MIT"
- },
- "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==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "iojs": ">= 1.0.0",
- "node": ">= 0.12.0"
- }
- },
- "node_modules/collect-v8-coverage": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
- "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/component-emitter": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
- "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/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/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==",
- "dev": true,
- "license": "MIT"
- },
- "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-parser": {
- "version": "1.4.7",
- "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
- "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
- "license": "MIT",
- "dependencies": {
- "cookie": "0.7.2",
- "cookie-signature": "1.0.6"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "license": "MIT"
- },
- "node_modules/cookiejar": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
- "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/create-jest": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
- "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "^29.6.3",
- "chalk": "^4.0.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "jest-config": "^29.7.0",
- "jest-util": "^29.7.0",
- "prompts": "^2.0.1"
- },
- "bin": {
- "create-jest": "bin/create-jest.js"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "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/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/dedent": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
- "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
- },
- "peerDependenciesMeta": {
- "babel-plugin-macros": {
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/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/detect-newline": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
- "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dezalgo": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
- "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "asap": "^2.0.0",
- "wrappy": "1"
- }
- },
- "node_modules/diff-sequences": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
- "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "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/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "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.404",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.404.tgz",
- "integrity": "sha512-3WJtd7/lVq2Jnuz6wed1l9+1ZD2u2Tet1/1NBc4Iedkmgbu+I7YuAqdAQ8T+VZtnwysMsAf3IqSq9D1gyZjA2g==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/emittery": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
- "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/emittery?sponsor=1"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/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/end-of-stream": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/error-ex": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
- "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
- "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.2",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
- "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
- "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": "2.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
- "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "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==",
- "dev": true,
- "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/execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.0",
- "human-signals": "^2.1.0",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.1",
- "onetime": "^5.1.2",
- "signal-exit": "^3.0.3",
- "strip-final-newline": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/exit": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
- "dev": true,
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/expect": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
- "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/expect-utils": "^29.7.0",
- "jest-get-type": "^29.6.3",
- "jest-matcher-utils": "^29.7.0",
- "jest-message-util": "^29.7.0",
- "jest-util": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/express": {
- "version": "4.22.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
- "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "~1.20.5",
- "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.15.1",
- "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/express-rate-limit": {
- "version": "8.6.2",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.6.2.tgz",
- "integrity": "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "ip-address": "^10.2.0"
- },
- "engines": {
- "node": ">= 16"
- },
- "funding": {
- "url": "https://github.com/sponsors/express-rate-limit"
- },
- "peerDependencies": {
- "express": ">= 4.11"
- }
- },
- "node_modules/express-rate-limit/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/express-rate-limit/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/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-safe-stringify": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
- "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "bser": "2.1.1"
- }
- },
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "license": "MIT"
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/form-data": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
- "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.4",
- "mime-types": "^2.1.35"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/formidable": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz",
- "integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@paralleldrive/cuid2": "^2.2.2",
- "dezalgo": "^1.0.4",
- "once": "^1.4.0",
- "qs": "^6.11.0"
- },
- "funding": {
- "url": "https://ko-fi.com/tunnckoCore/commissions"
- }
- },
- "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/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "license": "MIT"
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "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-package-type": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
- "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "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/get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "license": "MIT"
- },
- "node_modules/glob": {
- "version": "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",
- "dev": true,
- "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/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/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-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/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
- "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/html-escaper": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
- "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/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/human-signals": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
- "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=10.17.0"
- }
- },
- "node_modules/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/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/import-local": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
- "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pkg-dir": "^4.2.0",
- "resolve-cwd": "^3.0.0"
- },
- "bin": {
- "import-local-fixture": "fixtures/cli.js"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/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.",
- "dev": true,
- "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/ip-address": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz",
- "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
- }
- },
- "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-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/is-core-module": {
- "version": "2.16.2",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
- "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-generator-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
- "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/istanbul-lib-coverage": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
- "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-instrument": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
- "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@babel/core": "^7.23.9",
- "@babel/parser": "^7.23.9",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-coverage": "^3.2.0",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-instrument/node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-report": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
- "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^4.0.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-source-maps": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
- "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0",
- "source-map": "^0.6.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-source-maps/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/istanbul-lib-source-maps/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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/istanbul-reports": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
- "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
- "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/core": "^29.7.0",
- "@jest/types": "^29.6.3",
- "import-local": "^3.0.2",
- "jest-cli": "^29.7.0"
- },
- "bin": {
- "jest": "bin/jest.js"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/jest-changed-files": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
- "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "execa": "^5.0.0",
- "jest-util": "^29.7.0",
- "p-limit": "^3.1.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-circus": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
- "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "^29.7.0",
- "@jest/expect": "^29.7.0",
- "@jest/test-result": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "co": "^4.6.0",
- "dedent": "^1.0.0",
- "is-generator-fn": "^2.0.0",
- "jest-each": "^29.7.0",
- "jest-matcher-utils": "^29.7.0",
- "jest-message-util": "^29.7.0",
- "jest-runtime": "^29.7.0",
- "jest-snapshot": "^29.7.0",
- "jest-util": "^29.7.0",
- "p-limit": "^3.1.0",
- "pretty-format": "^29.7.0",
- "pure-rand": "^6.0.0",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-cli": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
- "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/core": "^29.7.0",
- "@jest/test-result": "^29.7.0",
- "@jest/types": "^29.6.3",
- "chalk": "^4.0.0",
- "create-jest": "^29.7.0",
- "exit": "^0.1.2",
- "import-local": "^3.0.2",
- "jest-config": "^29.7.0",
- "jest-util": "^29.7.0",
- "jest-validate": "^29.7.0",
- "yargs": "^17.3.1"
- },
- "bin": {
- "jest": "bin/jest.js"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/jest-config": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
- "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.7.0",
- "@jest/types": "^29.6.3",
- "babel-jest": "^29.7.0",
- "chalk": "^4.0.0",
- "ci-info": "^3.2.0",
- "deepmerge": "^4.2.2",
- "glob": "^7.1.3",
- "graceful-fs": "^4.2.9",
- "jest-circus": "^29.7.0",
- "jest-environment-node": "^29.7.0",
- "jest-get-type": "^29.6.3",
- "jest-regex-util": "^29.6.3",
- "jest-resolve": "^29.7.0",
- "jest-runner": "^29.7.0",
- "jest-util": "^29.7.0",
- "jest-validate": "^29.7.0",
- "micromatch": "^4.0.4",
- "parse-json": "^5.2.0",
- "pretty-format": "^29.7.0",
- "slash": "^3.0.0",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "@types/node": "*",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/jest-diff": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
- "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.6.3",
- "jest-get-type": "^29.6.3",
- "pretty-format": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-docblock": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
- "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "detect-newline": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-each": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
- "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/types": "^29.6.3",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.6.3",
- "jest-util": "^29.7.0",
- "pretty-format": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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-leak-detector": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
- "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jest-get-type": "^29.6.3",
- "pretty-format": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-matcher-utils": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
- "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.0.0",
- "jest-diff": "^29.7.0",
- "jest-get-type": "^29.6.3",
- "pretty-format": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "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==",
- "dev": true,
- "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-mock": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
- "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
- "dev": true,
- "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-pnp-resolver": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
- "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "peerDependencies": {
- "jest-resolve": "*"
- },
- "peerDependenciesMeta": {
- "jest-resolve": {
- "optional": true
- }
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-resolve": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
- "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.7.0",
- "jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.7.0",
- "jest-validate": "^29.7.0",
- "resolve": "^1.20.0",
- "resolve.exports": "^2.0.0",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-resolve-dependencies": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
- "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jest-regex-util": "^29.6.3",
- "jest-snapshot": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-runner": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
- "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/console": "^29.7.0",
- "@jest/environment": "^29.7.0",
- "@jest/test-result": "^29.7.0",
- "@jest/transform": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "graceful-fs": "^4.2.9",
- "jest-docblock": "^29.7.0",
- "jest-environment-node": "^29.7.0",
- "jest-haste-map": "^29.7.0",
- "jest-leak-detector": "^29.7.0",
- "jest-message-util": "^29.7.0",
- "jest-resolve": "^29.7.0",
- "jest-runtime": "^29.7.0",
- "jest-util": "^29.7.0",
- "jest-watcher": "^29.7.0",
- "jest-worker": "^29.7.0",
- "p-limit": "^3.1.0",
- "source-map-support": "0.5.13"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-runtime": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
- "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/environment": "^29.7.0",
- "@jest/fake-timers": "^29.7.0",
- "@jest/globals": "^29.7.0",
- "@jest/source-map": "^29.6.3",
- "@jest/test-result": "^29.7.0",
- "@jest/transform": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "cjs-module-lexer": "^1.0.0",
- "collect-v8-coverage": "^1.0.0",
- "glob": "^7.1.3",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.7.0",
- "jest-message-util": "^29.7.0",
- "jest-mock": "^29.7.0",
- "jest-regex-util": "^29.6.3",
- "jest-resolve": "^29.7.0",
- "jest-snapshot": "^29.7.0",
- "jest-util": "^29.7.0",
- "slash": "^3.0.0",
- "strip-bom": "^4.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-snapshot": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
- "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.11.6",
- "@babel/generator": "^7.7.2",
- "@babel/plugin-syntax-jsx": "^7.7.2",
- "@babel/plugin-syntax-typescript": "^7.7.2",
- "@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.7.0",
- "@jest/transform": "^29.7.0",
- "@jest/types": "^29.6.3",
- "babel-preset-current-node-syntax": "^1.0.0",
- "chalk": "^4.0.0",
- "expect": "^29.7.0",
- "graceful-fs": "^4.2.9",
- "jest-diff": "^29.7.0",
- "jest-get-type": "^29.6.3",
- "jest-matcher-utils": "^29.7.0",
- "jest-message-util": "^29.7.0",
- "jest-util": "^29.7.0",
- "natural-compare": "^1.4.0",
- "pretty-format": "^29.7.0",
- "semver": "^7.5.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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==",
- "dev": true,
- "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-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==",
- "dev": true,
- "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/camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/jest-watcher": {
- "version": "29.7.0",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
- "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jest/test-result": "^29.7.0",
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "jest-util": "^29.7.0",
- "string-length": "^4.0.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "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==",
- "dev": true,
- "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/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/js-yaml": {
- "version": "3.15.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz",
- "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsonwebtoken": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
- "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
- "license": "MIT",
- "dependencies": {
- "jws": "^4.0.1",
- "lodash.includes": "^4.3.0",
- "lodash.isboolean": "^3.0.3",
- "lodash.isinteger": "^4.0.4",
- "lodash.isnumber": "^3.0.3",
- "lodash.isplainobject": "^4.0.6",
- "lodash.isstring": "^4.0.1",
- "lodash.once": "^4.0.0",
- "ms": "^2.1.1",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- }
- },
- "node_modules/jsonwebtoken/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/jsonwebtoken/node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
- "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/kleur": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
- "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lodash.includes": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
- "license": "MIT"
- },
- "node_modules/lodash.isboolean": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
- "license": "MIT"
- },
- "node_modules/lodash.isinteger": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
- "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
- "license": "MIT"
- },
- "node_modules/lodash.isnumber": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
- "license": "MIT"
- },
- "node_modules/lodash.isplainobject": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
- "license": "MIT"
- },
- "node_modules/lodash.isstring": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
- "license": "MIT"
- },
- "node_modules/lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
- "license": "MIT"
- },
- "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==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/make-dir": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
- "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "semver": "^7.5.3"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/make-dir/node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tmpl": "1.0.5"
- }
- },
- "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/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/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/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
- "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "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/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "license": "MIT"
- },
- "node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.18",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
- "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "license": "MIT"
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/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/node-abi": {
- "version": "3.94.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz",
- "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-abi/node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/node-releases": {
- "version": "2.0.53",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz",
- "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
- "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/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/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
- "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
- "license": "MIT"
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
- "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "find-up": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.",
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/prompts": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
- "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "kleur": "^3.0.3",
- "sisteransi": "^1.0.5"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/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/pump": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
- "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/pure-rand": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
- "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
- "dev": true,
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/dubzzz"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fast-check"
- }
- ],
- "license": "MIT"
- },
- "node_modules/qs": {
- "version": "6.15.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
- "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "es-define-property": "^1.0.1",
- "side-channel": "^1.1.1"
- },
- "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/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/rc/node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.12",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
- "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "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-cwd": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
- "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "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/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/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/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/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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/side-channel": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
- "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.4",
- "side-channel-list": "^1.0.1",
- "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.1",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
- "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.4"
- },
- "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/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/sisteransi": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
- "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.13",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
- "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "escape-string-regexp": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-length": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
- "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "char-regex": "^1.0.2",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
- "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/superagent": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz",
- "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==",
- "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "component-emitter": "^1.3.0",
- "cookiejar": "^2.1.4",
- "debug": "^4.3.4",
- "fast-safe-stringify": "^2.1.1",
- "form-data": "^4.0.0",
- "formidable": "^2.1.2",
- "methods": "^1.1.2",
- "mime": "2.6.0",
- "qs": "^6.11.0",
- "semver": "^7.3.8"
- },
- "engines": {
- "node": ">=6.4.0 <13 || >=14"
- }
- },
- "node_modules/superagent/node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/superagent/node_modules/mime": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
- "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/superagent/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==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/superagent/node_modules/semver": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
- "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/supertest": {
- "version": "6.3.4",
- "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz",
- "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==",
- "deprecated": "Please upgrade to supertest v7.1.3+, see release notes at https://github.com/forwardemail/supertest/releases/tag/v7.1.3 - maintenance is supported by Forward Email @ https://forwardemail.net",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "methods": "^1.1.2",
- "superagent": "^8.1.2"
- },
- "engines": {
- "node": ">=6.4.0"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz",
- "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==",
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/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==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true,
- "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==",
- "dev": true,
- "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/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/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==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
- "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/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/undici-types": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
- "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
- "dev": true,
- "license": "MIT"
- },
- "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.3.1",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz",
- "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==",
- "dev": true,
- "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/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/v8-to-istanbul": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
- "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.12",
- "@types/istanbul-lib-coverage": "^2.0.1",
- "convert-source-map": "^2.0.0"
- },
- "engines": {
- "node": ">=10.12.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/walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "makeerror": "1.0.12"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "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==",
- "dev": true,
- "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/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==",
- "dev": true,
- "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/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/yargs": {
- "version": "17.7.3",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
- "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
- "dev": true,
- "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==",
- "dev": true,
- "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==",
- "dev": true,
- "license": "MIT",
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=18.0.0"
}
}
}
From 098c97cf6c46ea983361dd514cd8a025eaabaf8a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:49:04 +0000
Subject: [PATCH 09/13] chore: finalize EVODRON workspace verification
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
Dockerfile | 2 +-
evodron/.gitignore | 4 +
evodron/packages/api/src/routes/admin.ts | 18 +-
.../packages/cli/src/services/config.test.ts | 8 +
evodron/packages/db/src/client.d.ts | 5 -
evodron/packages/db/src/client.js | 58 --
evodron/packages/db/src/index.d.ts | 2 -
evodron/packages/db/src/index.js | 19 -
evodron/packages/db/src/migrate.ts | 4 +
evodron/packages/db/src/schema.d.ts | 859 ------------------
evodron/packages/db/src/schema.js | 89 --
evodron/packages/shared/src/index.d.ts | 111 ---
evodron/packages/shared/src/index.js | 24 -
13 files changed, 26 insertions(+), 1177 deletions(-)
delete mode 100644 evodron/packages/db/src/client.d.ts
delete mode 100644 evodron/packages/db/src/client.js
delete mode 100644 evodron/packages/db/src/index.d.ts
delete mode 100644 evodron/packages/db/src/index.js
delete mode 100644 evodron/packages/db/src/schema.d.ts
delete mode 100644 evodron/packages/db/src/schema.js
delete mode 100644 evodron/packages/shared/src/index.d.ts
delete mode 100644 evodron/packages/shared/src/index.js
diff --git a/Dockerfile b/Dockerfile
index 4bee4d1f..94eb7d62 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -39,4 +39,4 @@ EXPOSE 3000
USER node
-CMD ["sh", "-c", "npm run db:migrate && npm run db:seed && npm run start --workspace=@evodron/api"]
+CMD ["sh", "-c", "npm run db:migrate && npm run start --workspace=@evodron/api"]
diff --git a/evodron/.gitignore b/evodron/.gitignore
index 9e1d8af9..49281bee 100644
--- a/evodron/.gitignore
+++ b/evodron/.gitignore
@@ -1,5 +1,9 @@
node_modules/
dist/
+/packages/*/src/*.js
+/packages/*/src/*.d.ts
+/packages/*/src/*.js.map
+/packages/*/src/*.d.ts.map
*.js.map
.env
*.db
diff --git a/evodron/packages/api/src/routes/admin.ts b/evodron/packages/api/src/routes/admin.ts
index f3b66be6..50c02ad7 100644
--- a/evodron/packages/api/src/routes/admin.ts
+++ b/evodron/packages/api/src/routes/admin.ts
@@ -26,11 +26,11 @@ export async function adminRoutes(app: FastifyInstance) {
// ── POST /admin/abuse-flags/:id/resolve ───────────────────────────────────
- app.post(
+ app.post<{ Params: { id: string } }>(
'/abuse-flags/:id/resolve',
{ preHandler: [authenticateAdmin] },
- async (req: FastifyRequest, reply: FastifyReply) => {
- const { id } = req.params as { id: string };
+ async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
+ const { id } = req.params;
await db
.update(schema.abuseFlags)
@@ -43,11 +43,11 @@ export async function adminRoutes(app: FastifyInstance) {
// ── POST /admin/users/:id/ban ─────────────────────────────────────────────
- app.post(
+ app.post<{ Params: { id: string } }>(
'/users/:id/ban',
{ preHandler: [authenticateAdmin] },
- async (req: FastifyRequest, reply: FastifyReply) => {
- const { id } = req.params as { id: string };
+ async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
+ const { id } = req.params;
const timestamp = now();
await db
@@ -80,11 +80,11 @@ export async function adminRoutes(app: FastifyInstance) {
// ── PATCH /admin/reward-rules/:id ─────────────────────────────────────────
- app.patch(
+ app.patch<{ Params: { id: string } }>(
'/reward-rules/:id',
{ preHandler: [authenticateAdmin] },
- async (req: FastifyRequest, reply: FastifyReply) => {
- const { id } = req.params as { id: string };
+ async (req: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) => {
+ const { id } = req.params;
const body = req.body as { credits?: number; active?: boolean; description?: string };
const timestamp = now();
diff --git a/evodron/packages/cli/src/services/config.test.ts b/evodron/packages/cli/src/services/config.test.ts
index e2d85f35..8eab0657 100644
--- a/evodron/packages/cli/src/services/config.test.ts
+++ b/evodron/packages/cli/src/services/config.test.ts
@@ -9,13 +9,19 @@ function createTempConfigDir(): string {
}
describe('CLI config service', () => {
+ const createdDirs: string[] = [];
+
afterEach(() => {
delete process.env['EVODRON_CONFIG_DIR'];
delete process.env['EVODRON_API_URL'];
+ for (const dir of createdDirs.splice(0)) {
+ fs.rmSync(dir, { recursive: true, force: true });
+ }
});
it('saves and loads credentials from the configured directory', () => {
const dir = createTempConfigDir();
+ createdDirs.push(dir);
process.env['EVODRON_CONFIG_DIR'] = dir;
saveConfig({
@@ -35,6 +41,7 @@ describe('CLI config service', () => {
it('prefers the saved API URL over the environment fallback', () => {
const dir = createTempConfigDir();
+ createdDirs.push(dir);
process.env['EVODRON_CONFIG_DIR'] = dir;
process.env['EVODRON_API_URL'] = 'http://env.example.test';
@@ -45,6 +52,7 @@ describe('CLI config service', () => {
it('clears the persisted config file', () => {
const dir = createTempConfigDir();
+ createdDirs.push(dir);
process.env['EVODRON_CONFIG_DIR'] = dir;
saveConfig({ accessToken: 'token' });
diff --git a/evodron/packages/db/src/client.d.ts b/evodron/packages/db/src/client.d.ts
deleted file mode 100644
index 5df41e4b..00000000
--- a/evodron/packages/db/src/client.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { drizzle } from 'drizzle-orm/better-sqlite3';
-import * as schema from './schema';
-export declare function getDb(dbUrl?: string): ReturnType>;
-export { schema };
-export type Db = ReturnType;
diff --git a/evodron/packages/db/src/client.js b/evodron/packages/db/src/client.js
deleted file mode 100644
index 3e19027f..00000000
--- a/evodron/packages/db/src/client.js
+++ /dev/null
@@ -1,58 +0,0 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
- Object.defineProperty(o, "default", { enumerable: true, value: v });
-}) : function(o, v) {
- o["default"] = v;
-});
-var __importStar = (this && this.__importStar) || (function () {
- var ownKeys = function(o) {
- ownKeys = Object.getOwnPropertyNames || function (o) {
- var ar = [];
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
- return ar;
- };
- return ownKeys(o);
- };
- return function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
- __setModuleDefault(result, mod);
- return result;
- };
-})();
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.schema = void 0;
-exports.getDb = getDb;
-const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
-const better_sqlite3_2 = require("drizzle-orm/better-sqlite3");
-const schema = __importStar(require("./schema"));
-exports.schema = schema;
-let _db = null;
-function getDb(dbUrl) {
- if (_db)
- return _db;
- const url = dbUrl ?? process.env['EVODRON_DB_URL'] ?? 'file:./evodron.db';
- // Strip "file:" prefix for better-sqlite3
- const filePath = url.startsWith('file:') ? url.slice(5) : url;
- const sqlite = new better_sqlite3_1.default(filePath);
- sqlite.pragma('journal_mode = WAL');
- sqlite.pragma('foreign_keys = ON');
- _db = (0, better_sqlite3_2.drizzle)(sqlite, { schema });
- return _db;
-}
-//# sourceMappingURL=client.js.map
\ No newline at end of file
diff --git a/evodron/packages/db/src/index.d.ts b/evodron/packages/db/src/index.d.ts
deleted file mode 100644
index ecaa1564..00000000
--- a/evodron/packages/db/src/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './schema';
-export * from './client';
diff --git a/evodron/packages/db/src/index.js b/evodron/packages/db/src/index.js
deleted file mode 100644
index 2bf45469..00000000
--- a/evodron/packages/db/src/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-"use strict";
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- var desc = Object.getOwnPropertyDescriptor(m, k);
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
- desc = { enumerable: true, get: function() { return m[k]; } };
- }
- Object.defineProperty(o, k2, desc);
-}) : (function(o, m, k, k2) {
- if (k2 === undefined) k2 = k;
- o[k2] = m[k];
-}));
-var __exportStar = (this && this.__exportStar) || function(m, exports) {
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-__exportStar(require("./schema"), exports);
-__exportStar(require("./client"), exports);
-//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/evodron/packages/db/src/migrate.ts b/evodron/packages/db/src/migrate.ts
index 3e873536..c93a05f0 100644
--- a/evodron/packages/db/src/migrate.ts
+++ b/evodron/packages/db/src/migrate.ts
@@ -91,6 +91,10 @@ const migrations = [
`CREATE INDEX IF NOT EXISTS idx_abuse_flags_user ON abuse_flags(user_id)`,
`CREATE INDEX IF NOT EXISTS idx_ip_registry_hash ON ip_registry(ip_hash)`,
`CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user ON refresh_tokens(user_id)`,
+ `INSERT OR IGNORE INTO reward_rules (id, name, trigger, credits, active, description, updated_at) VALUES
+ ('rule-referrer', 'referral_active_referrer', 'referral_active', 100, 1, 'Credits awarded to the referrer when a referee reaches active status', datetime('now')),
+ ('rule-onboarding', 'referral_onboarding_referee', 'referral_onboarding', 50, 1, 'Onboarding credits awarded to a new user who joined via referral', datetime('now')),
+ ('rule-milestone-10', 'milestone_10_sessions', 'milestone_10_sessions', 25, 1, 'Bonus credits for completing 10 sessions', datetime('now'))`,
];
db.transaction(() => {
diff --git a/evodron/packages/db/src/schema.d.ts b/evodron/packages/db/src/schema.d.ts
deleted file mode 100644
index a81404b2..00000000
--- a/evodron/packages/db/src/schema.d.ts
+++ /dev/null
@@ -1,859 +0,0 @@
-export declare const users: any;
-export declare const sessions: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "sessions";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "sessions";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "user_id";
- tableName: "sessions";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- startedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "started_at";
- tableName: "sessions";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- endedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "ended_at";
- tableName: "sessions";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- commandsCount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "commands_count";
- tableName: "sessions";
- dataType: "number";
- columnType: "SQLiteInteger";
- data: number;
- driverParam: number;
- notNull: true;
- hasDefault: true;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: undefined;
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {}>;
- clientVersion: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "client_version";
- tableName: "sessions";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- ipHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "ip_hash";
- tableName: "sessions";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
-export declare const referrals: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "referrals";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- referrerId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "referrer_id";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- refereeId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "referee_id";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "status";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: "pending" | "active" | "rewarded" | "fraud";
- driverParam: string;
- notNull: true;
- hasDefault: true;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: ["pending", "active", "rewarded", "fraud"];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- activatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "activated_at";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- rewardedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "rewarded_at";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "created_at";
- tableName: "referrals";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
-export declare const rewards: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "rewards";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "rewards";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "user_id";
- tableName: "rewards";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- type: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "type";
- tableName: "rewards";
- dataType: "string";
- columnType: "SQLiteText";
- data: "referral_active" | "referral_onboarding" | "milestone" | "manual";
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: ["referral_active", "referral_onboarding", "milestone", "manual"];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- amount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "amount";
- tableName: "rewards";
- dataType: "number";
- columnType: "SQLiteInteger";
- data: number;
- driverParam: number;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: undefined;
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {}>;
- source: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "source";
- tableName: "rewards";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "created_at";
- tableName: "rewards";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
-export declare const rewardRules: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "reward_rules";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "reward_rules";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- name: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "name";
- tableName: "reward_rules";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- trigger: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "trigger";
- tableName: "reward_rules";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- credits: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "credits";
- tableName: "reward_rules";
- dataType: "number";
- columnType: "SQLiteInteger";
- data: number;
- driverParam: number;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: undefined;
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {}>;
- active: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "active";
- tableName: "reward_rules";
- dataType: "boolean";
- columnType: "SQLiteBoolean";
- data: boolean;
- driverParam: number;
- notNull: true;
- hasDefault: true;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: undefined;
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {}>;
- description: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "description";
- tableName: "reward_rules";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "updated_at";
- tableName: "reward_rules";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
-export declare const abuseFlags: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "abuse_flags";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "abuse_flags";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "user_id";
- tableName: "abuse_flags";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- reason: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "reason";
- tableName: "abuse_flags";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- detail: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "detail";
- tableName: "abuse_flags";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- resolvedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "resolved_at";
- tableName: "abuse_flags";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- flaggedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "flagged_at";
- tableName: "abuse_flags";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
-export declare const ipRegistry: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "ip_registry";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "ip_registry";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- ipHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "ip_hash";
- tableName: "ip_registry";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "user_id";
- tableName: "ip_registry";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- seenAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "seen_at";
- tableName: "ip_registry";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
-export declare const refreshTokens: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
- name: "refresh_tokens";
- schema: undefined;
- columns: {
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "id";
- tableName: "refresh_tokens";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: true;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- userId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "user_id";
- tableName: "refresh_tokens";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- tokenHash: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "token_hash";
- tableName: "refresh_tokens";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- expiresAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "expires_at";
- tableName: "refresh_tokens";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "created_at";
- tableName: "refresh_tokens";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: true;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- revokedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
- name: "revoked_at";
- tableName: "refresh_tokens";
- dataType: "string";
- columnType: "SQLiteText";
- data: string;
- driverParam: string;
- notNull: false;
- hasDefault: false;
- isPrimaryKey: false;
- isAutoincrement: false;
- hasRuntimeDefault: false;
- enumValues: [string, ...string[]];
- baseColumn: never;
- identity: undefined;
- generated: undefined;
- }, {}, {
- length: number | undefined;
- }>;
- };
- dialect: "sqlite";
-}>;
diff --git a/evodron/packages/db/src/schema.js b/evodron/packages/db/src/schema.js
deleted file mode 100644
index 4514ae77..00000000
--- a/evodron/packages/db/src/schema.js
+++ /dev/null
@@ -1,89 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.refreshTokens = exports.ipRegistry = exports.abuseFlags = exports.rewardRules = exports.rewards = exports.referrals = exports.sessions = exports.users = void 0;
-const sqlite_core_1 = require("drizzle-orm/sqlite-core");
-// ─── users ────────────────────────────────────────────────────────────────────
-exports.users = (0, sqlite_core_1.sqliteTable)('users', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- email: (0, sqlite_core_1.text)('email').notNull().unique(),
- username: (0, sqlite_core_1.text)('username').notNull().unique(),
- passwordHash: (0, sqlite_core_1.text)('password_hash').notNull(),
- referralCode: (0, sqlite_core_1.text)('referral_code').notNull().unique(),
- referredBy: (0, sqlite_core_1.text)('referred_by').references(() => exports.users.id),
- credits: (0, sqlite_core_1.integer)('credits').notNull().default(0),
- level: (0, sqlite_core_1.text)('level', { enum: ['bronze', 'silver', 'gold'] }).notNull().default('bronze'),
- isAdmin: (0, sqlite_core_1.integer)('is_admin', { mode: 'boolean' }).notNull().default(false),
- isBanned: (0, sqlite_core_1.integer)('is_banned', { mode: 'boolean' }).notNull().default(false),
- consentMetrics: (0, sqlite_core_1.integer)('consent_metrics', { mode: 'boolean' }).notNull().default(false),
- createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
- updatedAt: (0, sqlite_core_1.text)('updated_at').notNull(),
-});
-// ─── sessions ─────────────────────────────────────────────────────────────────
-exports.sessions = (0, sqlite_core_1.sqliteTable)('sessions', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
- startedAt: (0, sqlite_core_1.text)('started_at').notNull(),
- endedAt: (0, sqlite_core_1.text)('ended_at'),
- commandsCount: (0, sqlite_core_1.integer)('commands_count').notNull().default(0),
- clientVersion: (0, sqlite_core_1.text)('client_version'),
- ipHash: (0, sqlite_core_1.text)('ip_hash'),
-});
-// ─── referrals ────────────────────────────────────────────────────────────────
-exports.referrals = (0, sqlite_core_1.sqliteTable)('referrals', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- referrerId: (0, sqlite_core_1.text)('referrer_id').notNull().references(() => exports.users.id),
- refereeId: (0, sqlite_core_1.text)('referee_id').notNull().unique().references(() => exports.users.id),
- status: (0, sqlite_core_1.text)('status', { enum: ['pending', 'active', 'rewarded', 'fraud'] })
- .notNull()
- .default('pending'),
- activatedAt: (0, sqlite_core_1.text)('activated_at'),
- rewardedAt: (0, sqlite_core_1.text)('rewarded_at'),
- createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
-});
-// ─── rewards ──────────────────────────────────────────────────────────────────
-exports.rewards = (0, sqlite_core_1.sqliteTable)('rewards', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
- type: (0, sqlite_core_1.text)('type', {
- enum: ['referral_active', 'referral_onboarding', 'milestone', 'manual'],
- }).notNull(),
- amount: (0, sqlite_core_1.integer)('amount').notNull(),
- source: (0, sqlite_core_1.text)('source').notNull(),
- createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
-});
-// ─── reward_rules ─────────────────────────────────────────────────────────────
-exports.rewardRules = (0, sqlite_core_1.sqliteTable)('reward_rules', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- name: (0, sqlite_core_1.text)('name').notNull().unique(),
- trigger: (0, sqlite_core_1.text)('trigger').notNull(),
- credits: (0, sqlite_core_1.integer)('credits').notNull(),
- active: (0, sqlite_core_1.integer)('active', { mode: 'boolean' }).notNull().default(true),
- description: (0, sqlite_core_1.text)('description'),
- updatedAt: (0, sqlite_core_1.text)('updated_at').notNull(),
-});
-// ─── abuse_flags ──────────────────────────────────────────────────────────────
-exports.abuseFlags = (0, sqlite_core_1.sqliteTable)('abuse_flags', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
- reason: (0, sqlite_core_1.text)('reason').notNull(),
- detail: (0, sqlite_core_1.text)('detail'),
- resolvedAt: (0, sqlite_core_1.text)('resolved_at'),
- flaggedAt: (0, sqlite_core_1.text)('flagged_at').notNull(),
-});
-// ─── ip_registry ──────────────────────────────────────────────────────────────
-exports.ipRegistry = (0, sqlite_core_1.sqliteTable)('ip_registry', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- ipHash: (0, sqlite_core_1.text)('ip_hash').notNull(),
- userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
- seenAt: (0, sqlite_core_1.text)('seen_at').notNull(),
-});
-// ─── refresh_tokens ───────────────────────────────────────────────────────────
-exports.refreshTokens = (0, sqlite_core_1.sqliteTable)('refresh_tokens', {
- id: (0, sqlite_core_1.text)('id').primaryKey(),
- userId: (0, sqlite_core_1.text)('user_id').notNull().references(() => exports.users.id),
- tokenHash: (0, sqlite_core_1.text)('token_hash').notNull().unique(),
- expiresAt: (0, sqlite_core_1.text)('expires_at').notNull(),
- createdAt: (0, sqlite_core_1.text)('created_at').notNull(),
- revokedAt: (0, sqlite_core_1.text)('revoked_at'),
-});
-//# sourceMappingURL=schema.js.map
\ No newline at end of file
diff --git a/evodron/packages/shared/src/index.d.ts b/evodron/packages/shared/src/index.d.ts
deleted file mode 100644
index 8dd2c111..00000000
--- a/evodron/packages/shared/src/index.d.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { z } from 'zod';
-export declare const RegisterSchema: z.ZodObject<{
- email: z.ZodString;
- username: z.ZodString;
- password: z.ZodString;
- referralCode: z.ZodOptional;
-}, "strip", z.ZodTypeAny, {
- email: string;
- username: string;
- password: string;
- referralCode?: string | undefined;
-}, {
- email: string;
- username: string;
- password: string;
- referralCode?: string | undefined;
-}>;
-export type RegisterInput = z.infer;
-export declare const LoginSchema: z.ZodObject<{
- email: z.ZodString;
- password: z.ZodString;
-}, "strip", z.ZodTypeAny, {
- email: string;
- password: string;
-}, {
- email: string;
- password: string;
-}>;
-export type LoginInput = z.infer;
-export interface UserPublic {
- id: string;
- email: string;
- username: string;
- referralCode: string;
- credits: number;
- level: UserLevel;
- createdAt: string;
-}
-export type UserLevel = 'bronze' | 'silver' | 'gold';
-export declare const StartSessionSchema: z.ZodObject<{
- clientVersion: z.ZodOptional;
-}, "strip", z.ZodTypeAny, {
- clientVersion?: string | undefined;
-}, {
- clientVersion?: string | undefined;
-}>;
-export type StartSessionInput = z.infer;
-export declare const EndSessionSchema: z.ZodObject<{
- sessionId: z.ZodString;
- commandsCount: z.ZodNumber;
-}, "strip", z.ZodTypeAny, {
- sessionId: string;
- commandsCount: number;
-}, {
- sessionId: string;
- commandsCount: number;
-}>;
-export type EndSessionInput = z.infer;
-export type ReferralStatus = 'pending' | 'active' | 'rewarded' | 'fraud';
-export interface ReferralStats {
- code: string;
- link: string;
- totalReferrals: number;
- activeReferrals: number;
- pendingReferrals: number;
- totalCreditsEarned: number;
- referrals: ReferralEntry[];
-}
-export interface ReferralEntry {
- id: string;
- refereeUsername: string;
- status: ReferralStatus;
- createdAt: string;
-}
-export type RewardType = 'referral_active' | 'referral_onboarding' | 'milestone' | 'manual';
-export interface Reward {
- id: string;
- type: RewardType;
- amount: number;
- source: string;
- createdAt: string;
-}
-export interface RewardRule {
- id: string;
- name: string;
- trigger: string;
- credits: number;
- active: boolean;
-}
-export interface UserStats {
- totalSessions: number;
- totalCommands: number;
- totalCredits: number;
- level: UserLevel;
- joinedAt: string;
-}
-export interface ApiSuccess {
- success: true;
- data: T;
-}
-export interface ApiError {
- success: false;
- error: string;
- code?: string;
-}
-export type ApiResponse = ApiSuccess | ApiError;
-export interface AuthTokens {
- accessToken: string;
- refreshToken: string;
- expiresIn: number;
-}
diff --git a/evodron/packages/shared/src/index.js b/evodron/packages/shared/src/index.js
deleted file mode 100644
index 0727b658..00000000
--- a/evodron/packages/shared/src/index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.EndSessionSchema = exports.StartSessionSchema = exports.LoginSchema = exports.RegisterSchema = void 0;
-const zod_1 = require("zod");
-// ─── User ────────────────────────────────────────────────────────────────────
-exports.RegisterSchema = zod_1.z.object({
- email: zod_1.z.string().email(),
- username: zod_1.z.string().min(3).max(32).regex(/^[a-zA-Z0-9_-]+$/),
- password: zod_1.z.string().min(8).max(128),
- referralCode: zod_1.z.string().length(8).optional(),
-});
-exports.LoginSchema = zod_1.z.object({
- email: zod_1.z.string().email(),
- password: zod_1.z.string().min(1),
-});
-// ─── Session ─────────────────────────────────────────────────────────────────
-exports.StartSessionSchema = zod_1.z.object({
- clientVersion: zod_1.z.string().optional(),
-});
-exports.EndSessionSchema = zod_1.z.object({
- sessionId: zod_1.z.string().uuid(),
- commandsCount: zod_1.z.number().int().min(0),
-});
-//# sourceMappingURL=index.js.map
\ No newline at end of file
From b4b5f8d3f7cde42b1b65c4a0ad7a98db9b8fd45a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 18:56:37 +0000
Subject: [PATCH 10/13] Initial plan
From 0101e3ee5ecadbed5a67a96f2980c2afc787d806 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 19:01:56 +0000
Subject: [PATCH 11/13] Fix CI: build shared packages before linting to resolve
TS2307/TS7006 errors
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
evodron/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/evodron/package.json b/evodron/package.json
index e43c52b0..67a434b6 100644
--- a/evodron/package.json
+++ b/evodron/package.json
@@ -9,7 +9,7 @@
"scripts": {
"build": "npm run build --workspace=@evodron/shared && npm run build --workspace=@evodron/db && npm run build --workspace=@evodron/api && npm run build --workspace=@evodron/cli",
"test": "npm run test --workspaces --if-present",
- "lint": "npm run lint --workspaces --if-present",
+ "lint": "npm run build --workspace=@evodron/shared && npm run build --workspace=@evodron/db && npm run lint --workspaces --if-present",
"dev:api": "npm run dev --workspace=packages/api",
"dev:cli": "npm run dev --workspace=packages/cli",
"db:migrate": "npm run migrate --workspace=packages/db",
From 0e73c988a44d809bc851439411adecffb77b7b7d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 11 Aug 2026 19:00:55 +0000
Subject: [PATCH 12/13] Fix CI: build @evodron/shared and @evodron/db before
running lint
Co-authored-by: julesdemangeot-ship-it <307666271+julesdemangeot-ship-it@users.noreply.github.com>
---
.github/workflows/ci.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eb7dd26c..10a8abb0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,6 +24,10 @@ jobs:
working-directory: evodron
run: npm ci
+ - name: Build dependencies
+ working-directory: evodron
+ run: npm run build -w @evodron/shared -w @evodron/db
+
- name: Lint workspace
working-directory: evodron
run: npm run lint
From e5d8f8752e414e8c4b51e71e7f3b7b78631b87ee Mon Sep 17 00:00:00 2001
From: Jules Demangeot
<307666271+julesdemangeot-ship-it@users.noreply.github.com>
Date: Wed, 12 Aug 2026 06:16:03 +0200
Subject: [PATCH 13/13] Update Dockerfile
---
Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dockerfile b/Dockerfile
index 94eb7d62..e69f3bac 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,7 +30,7 @@ COPY --from=builder /app/evodron/packages/api/dist ./packages/api/dist
COPY --from=builder /app/evodron/packages/db/dist ./packages/db/dist
COPY --from=builder /app/evodron/packages/shared/dist ./packages/shared/dist
-VOLUME ["/data"]
+# VOLUME ["/data"]
ENV EVODRON_DB_URL=file:/data/evodron.db
ENV EVODRON_API_HOST=0.0.0.0
ENV EVODRON_API_PORT=3000