diff --git a/package-lock.json b/package-lock.json index 50ee78a..e22e465 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,11 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@anthropic-ai/claude-code": "^2.1.7", - "@chittyapps/chittycloude-mcp": "^1.0.0", - "@clerk/backend": "^1.0.0", "@clerk/clerk-react": "^5.0.0", - "@clerk/clerk-sdk-node": "^5.0.0", - "@clerk/express": "^2.0.1", - "@clerk/types": "^4.0.0", - "@google-cloud/storage": "^7.16.0", "@hono/zod-validator": "^0.8.0", "@hookform/resolvers": "^3.10.0", "@jridgewell/trace-mapping": "^0.3.25", "@neondatabase/serverless": "^0.10.4", - "@notionhq/client": "^2.2.14", "@radix-ui/react-accordion": "^1.2.4", "@radix-ui/react-alert-dialog": "^1.1.7", "@radix-ui/react-aspect-ratio": "^1.1.3", @@ -50,7 +42,6 @@ "@radix-ui/react-toggle-group": "^1.1.3", "@radix-ui/react-tooltip": "^1.2.8", "@tanstack/react-query": "^5.60.5", - "@types/memoizee": "^0.4.12", "@uppy/aws-s3": "^4.3.2", "@uppy/core": "^5.2.0", "@uppy/dashboard": "^4.4.3", @@ -61,24 +52,17 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "connect-pg-simple": "^10.0.0", "date-fns": "^3.6.0", "drizzle-orm": "^0.39.1", "drizzle-zod": "^0.7.0", "embla-carousel-react": "^8.6.0", - "express": "^4.22.1", - "express-session": "^1.19.0", "framer-motion": "^11.13.1", - "google-auth-library": "^10.2.1", "hono": "^4.12.18", "input-otp": "^1.4.2", "jose": "^6.2.3", "lucide-react": "^0.453.0", - "memoizee": "^0.4.17", - "memorystore": "^1.6.7", "next-themes": "^0.4.6", "openai": "^5.12.0", - "openid-client": "^6.6.3", "postgres": "^3.4.9", "react": "^18.3.1", "react-day-picker": "^8.10.1", @@ -92,39 +76,33 @@ "tw-animate-css": "^1.2.5", "vaul": "^1.1.2", "wouter": "^3.3.5", - "ws": "^8.18.0", "zod": "^3.24.2", "zod-validation-error": "^3.4.0" }, "devDependencies": { + "@cloudflare/workers-types": "^4.20260517.1", "@tailwindcss/typography": "^0.5.15", "@tailwindcss/vite": "^4.2.1", "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.8.0", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", - "@types/connect-pg-simple": "^7.0.3", - "@types/express": "4.17.21", - "@types/express-session": "^1.18.2", "@types/node": "20.16.11", - "@types/passport": "^1.0.16", - "@types/passport-local": "^1.0.38", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", - "@types/ws": "^8.5.13", "@vitejs/plugin-react": "^4.3.2", "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", "autoprefixer": "^10.4.20", + "concurrently": "^9.0.0", "drizzle-kit": "^0.18.1", - "esbuild": "^0.25.12", "jsdom": "^28.1.0", "postcss": "^8.4.47", "tailwindcss": "^3.4.17", - "tsx": "^4.19.1", "typescript": "5.6.3", "vite": "^7.1.11", - "vitest": "^4.0.18" + "vitest": "^4.0.18", + "wrangler": "^4.0.0" }, "optionalDependencies": { "bufferutil": "^4.0.8" @@ -171,28 +149,6 @@ "node": ">=6.0.0" } }, - "node_modules/@anthropic-ai/claude-code": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-2.1.7.tgz", - "integrity": "sha512-nETDGeuXk/pwUpja/dlVY8dch4doTtue381BjaNqWiMPSqpY4PPg8dDbTqAYpbkIi1sgli7met+okAeDsXVTpg==", - "license": "SEE LICENSE IN README.md", - "bin": { - "claude": "cli.js" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "^0.33.5", - "@img/sharp-darwin-x64": "^0.33.5", - "@img/sharp-linux-arm": "^0.33.5", - "@img/sharp-linux-arm64": "^0.33.5", - "@img/sharp-linux-x64": "^0.33.5", - "@img/sharp-linuxmusl-arm64": "^0.33.5", - "@img/sharp-linuxmusl-x64": "^0.33.5", - "@img/sharp-win32-x64": "^0.33.5" - } - }, "node_modules/@asamuzakjp/css-color": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.0.1.tgz", @@ -567,61 +523,6 @@ "specificity": "bin/cli.js" } }, - "node_modules/@chittyapps/chittycloude-mcp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@chittyapps/chittycloude-mcp/-/chittycloude-mcp-1.0.0.tgz", - "integrity": "sha512-KBzBylJCXFJNkqhGI7WkFnn6UvWMudMrLbI7iifjDrp9RzDNfkgGLf9+G6BKfaZvxTNwXEneuG6yMmqpqQ+vDQ==", - "license": "MIT", - "dependencies": { - "@cloudflare/workers-types": "^4.20241106.0", - "@modelcontextprotocol/sdk": "^1.17.4", - "axios": "^1.7.7", - "dotenv": "^16.4.5", - "pino": "^9.7.0", - "pino-pretty": "^13.0.0", - "zod": "^3.24.4" - }, - "bin": { - "chittycloud-mcp": "working-index.js" - }, - "engines": { - "node": ">=22.0.0", - "npm": ">= 10" - } - }, - "node_modules/@clerk/backend": { - "version": "1.34.0", - "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-1.34.0.tgz", - "integrity": "sha512-9rZ8hQJVpX5KX2bEpiuVXfpjhojQCiqCWADJDdCI0PCeKxn58Ep0JPYiIcczg4VKUc3a7jve9vXylykG2XajLQ==", - "license": "MIT", - "dependencies": { - "@clerk/shared": "^3.9.5", - "@clerk/types": "^4.59.3", - "cookie": "1.0.2", - "snakecase-keys": "8.0.1", - "tslib": "2.8.1" - }, - "engines": { - "node": ">=18.17.0" - }, - "peerDependencies": { - "svix": "^1.62.0" - }, - "peerDependenciesMeta": { - "svix": { - "optional": true - } - } - }, - "node_modules/@clerk/backend/node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/@clerk/clerk-react": { "version": "5.47.0", "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-5.47.0.tgz", @@ -640,35 +541,19 @@ "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" } }, - "node_modules/@clerk/clerk-sdk-node": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-5.1.6.tgz", - "integrity": "sha512-KeF5p0XP0gNoCx+YIHrfrkNNADBz8ZabwPAhOiJZ9Wo14r93WlzRA51IE0Qgteej8IpWwnvKu4/MpiV7FFoLqA==", - "deprecated": "January 10 2025 marks the end of support for @clerk/clerk-sdk-node as previously announced in our October 2024 deprecation notice. Express users can migrate to the @clerk/express package. For more information, you can find our changelog here: https://clerk.com/changelog/2025-01-10-node-sdk-eol", - "license": "MIT", - "dependencies": { - "@clerk/backend": "^1.21.6", - "@clerk/shared": "^2.20.6", - "@clerk/types": "^4.40.2", - "tslib": "2.4.1" - }, - "engines": { - "node": ">=18.17.0" - } - }, - "node_modules/@clerk/clerk-sdk-node/node_modules/@clerk/shared": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-2.22.0.tgz", - "integrity": "sha512-VWBeddOJVa3sqUPdvquaaQYw4h5hACSG3EUDOW7eSu2F6W3BXUozyLJQPBJ9C0MuoeHhOe/DeV8x2KqOgxVZaQ==", + "node_modules/@clerk/shared": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.25.0.tgz", + "integrity": "sha512-2Vb6NQqBA+1g7kfGct/OlSFmzU54/s4BQp3qeHwDqW1FgaU4MuXbqfBClI6AatxOC8Ux8W16Rvf705ViwFSxlw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@clerk/types": "^4.46.1", + "@clerk/types": "^4.86.0", "dequal": "2.0.3", "glob-to-regexp": "0.4.1", "js-cookie": "3.0.5", - "std-env": "^3.7.0", - "swr": "^2.2.0" + "std-env": "^3.9.0", + "swr": "2.3.4" }, "engines": { "node": ">=18.17.0" @@ -686,129 +571,159 @@ } } }, - "node_modules/@clerk/clerk-sdk-node/node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", - "license": "0BSD" - }, - "node_modules/@clerk/express": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@clerk/express/-/express-2.0.1.tgz", - "integrity": "sha512-MMwTqn1aM6yHf8JWkA7F7YQQWFg+CNmzKok9zC6YIIEVITk60br1rlZmQR6cVYaBNUp6xqJ/ewzCvfBI8xwdKA==", + "node_modules/@clerk/types": { + "version": "4.86.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.86.0.tgz", + "integrity": "sha512-YFaOYIAZWbpXehAmtgUB0YNf1v5b/hlwePvdqxlD5vdwrNsap28RpupWZat0hp1+PTtb9uAwSa5AFCOxkYLUJQ==", "license": "MIT", "dependencies": { - "@clerk/backend": "^3.0.1", - "@clerk/shared": "^4.0.0", - "tslib": "2.8.1" + "csstype": "3.1.3" }, "engines": { - "node": ">=20.9.0" - }, - "peerDependencies": { - "express": "^4.17.0 || ^5.0.0" + "node": ">=18.17.0" } }, - "node_modules/@clerk/express/node_modules/@clerk/backend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-3.0.1.tgz", - "integrity": "sha512-U5E+KpNlFlaJRdpOoOltIV8o1YjTWw5affsugEb/kIvGceSP6SzvNEBr/TnCY+2yu87Vq22ShEycpQBlse2Bkw==", - "license": "MIT", - "dependencies": { - "@clerk/shared": "^4.0.0", - "standardwebhooks": "^1.0.0", - "tslib": "2.8.1" - }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", + "dev": true, + "license": "MIT OR Apache-2.0", "engines": { - "node": ">=20.9.0" + "node": ">=22.0.0" } }, - "node_modules/@clerk/express/node_modules/@clerk/shared": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-4.0.0.tgz", - "integrity": "sha512-Z3QhVud7FM9SBgSGxyUdC+nDg6vro+5zJ5gDO1To3FDzRLWKW4xIGd5y8UBqWZMMMHWaSDiZvYlUynb+gs8PnQ==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.90.16", - "dequal": "2.0.3", - "glob-to-regexp": "0.4.1", - "js-cookie": "3.0.5", - "std-env": "^3.9.0" - }, - "engines": { - "node": ">=20.9.0" - }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz", + "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "dev": true, + "license": "MIT OR Apache-2.0", "peerDependencies": { - "react": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0", - "react-dom": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0" + "unenv": "2.0.0-rc.24", + "workerd": ">1.20260305.0 <2.0.0-0" }, "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { + "workerd": { "optional": true } } }, - "node_modules/@clerk/express/node_modules/@tanstack/query-core": { - "version": "5.90.16", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.16.tgz", - "integrity": "sha512-MvtWckSVufs/ja463/K4PyJeqT+HMlJWtw6PrCpywznd2NSgO3m4KwO9RqbFqGg6iDE8vVMFWMeQI4Io3eEYww==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260515.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260515.1.tgz", + "integrity": "sha512-Wtw44el2pNbzixvTkWdfeBDTrQwQbJRz7/JUvPKV27I0pQWXbhNJPpM8cstq/pbrU5AGcA/HjFH6yPMRTIRKig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" } }, - "node_modules/@clerk/shared": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.25.0.tgz", - "integrity": "sha512-2Vb6NQqBA+1g7kfGct/OlSFmzU54/s4BQp3qeHwDqW1FgaU4MuXbqfBClI6AatxOC8Ux8W16Rvf705ViwFSxlw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@clerk/types": "^4.86.0", - "dequal": "2.0.3", - "glob-to-regexp": "0.4.1", - "js-cookie": "3.0.5", - "std-env": "^3.9.0", - "swr": "2.3.4" - }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260515.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260515.1.tgz", + "integrity": "sha512-X8EqkZej6FfmhF9AVAQ3FhyQRr9acS4RcDunMU2YiuxKHF1IU8zzH3vY30/POaG+rUu9vGDp/VgUl49VPenHJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=18.17.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", - "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "node": ">=16" } }, - "node_modules/@clerk/types": { - "version": "4.86.0", - "resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.86.0.tgz", - "integrity": "sha512-YFaOYIAZWbpXehAmtgUB0YNf1v5b/hlwePvdqxlD5vdwrNsap28RpupWZat0hp1+PTtb9uAwSa5AFCOxkYLUJQ==", + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260515.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260515.1.tgz", + "integrity": "sha512-CDC89QxQ7Y7t7RG1Jd9vj/qolE1sQRkI2OSEuV5BMJi0vW/gV4OVG6xjpdK3b1OYnSWDzF7NpvlR5Yg86q7k4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260515.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260515.1.tgz", + "integrity": "sha512-WxbW/PToYES4fvHXzsr/5qOiETQs/Z9iZ0mjSZAiEwq5cMLZemzGN0COx+uFb9OvQwzh6Pg159qPFnw3+i9FuA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260515.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260515.1.tgz", + "integrity": "sha512-WmV/iv+MHjYsvkcMVzpM2B5/mf06UUkdpVhZrtMfV9graWjBGPYFvE/eab8748RPVGKh1Xe1vXofLzDSwc08lA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workers-types": { + "version": "4.20260517.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260517.1.tgz", + "integrity": "sha512-OjavgX6VpYoWlKg2xPgLKIhBeiJvNdwFVK8E1P6hF02wh1oEt1sZpTzbp9kdohprqjXo6UVqs7/AuIH0wxIcbw==", + "dev": true, + "license": "MIT OR Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "license": "MIT", "dependencies": { - "csstype": "3.1.3" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=18.17.0" + "node": ">=12" } }, - "node_modules/@cloudflare/workers-types": { - "version": "4.20250830.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250830.0.tgz", - "integrity": "sha512-uAGZFqEBFnCiwIokxMnrrtjIkT8qyGT1LACSScEUyW7nKmtD0Viykp9QZWrIlssyEp/MDB6XsdALF8y6upxpcg==", - "license": "MIT OR Apache-2.0" + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } }, "node_modules/@csstools/color-helpers": { "version": "6.0.2", @@ -942,6 +857,17 @@ "node": ">=20.19.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -1436,289 +1362,59 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" }, - "node_modules/@google-cloud/paginator": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", - "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", - "license": "Apache-2.0", - "dependencies": { - "arrify": "^2.0.0", - "extend": "^3.0.2" - }, - "engines": { - "node": ">=14.0.0" + "node_modules/@hono/zod-validator": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@hono/zod-validator/-/zod-validator-0.8.0.tgz", + "integrity": "sha512-5uS4S1/LKtZQYvD4BtpPUFkOv8d1wNxHHrChm26buMiEYc1FrHWvDUaKVBwkiVtvSExHSpLGDvcnpI2Copyj9w==", + "license": "MIT", + "peerDependencies": { + "hono": ">=4.10.0", + "zod": "^3.25.0 || ^4.0.0" } }, - "node_modules/@google-cloud/projectify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", - "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14.0.0" + "node_modules/@hookform/resolvers": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", + "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", + "peerDependencies": { + "react-hook-form": "^7.0.0" } }, - "node_modules/@google-cloud/promisify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", - "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", - "license": "Apache-2.0", + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/@google-cloud/storage": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.16.0.tgz", - "integrity": "sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw==", - "license": "Apache-2.0", - "dependencies": { - "@google-cloud/paginator": "^5.0.0", - "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "<4.1.0", - "abort-controller": "^3.0.0", - "async-retry": "^1.3.3", - "duplexify": "^4.1.3", - "fast-xml-parser": "^4.4.1", - "gaxios": "^6.0.2", - "google-auth-library": "^9.6.3", - "html-entities": "^2.5.2", - "mime": "^3.0.0", - "p-limit": "^3.0.1", - "retry-request": "^7.0.0", - "teeny-request": "^9.0.0", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=14" + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@google-cloud/storage/node_modules/gcp-metadata": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", - "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^6.1.1", - "google-logging-utils": "^0.0.2", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/storage/node_modules/google-auth-library": { - "version": "9.15.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", - "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/storage/node_modules/google-logging-utils": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", - "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/storage/node_modules/gtoken": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", - "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", - "license": "MIT", - "dependencies": { - "gaxios": "^6.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/storage/node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@hono/node-server": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.11.tgz", - "integrity": "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==", - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, - "node_modules/@hono/zod-validator": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@hono/zod-validator/-/zod-validator-0.8.0.tgz", - "integrity": "sha512-5uS4S1/LKtZQYvD4BtpPUFkOv8d1wNxHHrChm26buMiEYc1FrHWvDUaKVBwkiVtvSExHSpLGDvcnpI2Copyj9w==", - "license": "MIT", - "peerDependencies": { - "hono": ">=4.10.0", - "zod": "^3.25.0 || ^4.0.0" - } - }, - "node_modules/@hookform/resolvers": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", - "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", - "peerDependencies": { - "react-hook-form": "^7.0.0" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", "cpu": [ - "arm64" + "riscv64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1728,13 +1424,14 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", "cpu": [ - "x64" + "s390x" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1744,13 +1441,14 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", "cpu": [ - "arm" + "ppc64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1763,16 +1461,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-ppc64": "1.2.4" } }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", "cpu": [ - "arm64" + "riscv64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1785,16 +1484,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ - "x64" + "s390x" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1807,60 +1507,57 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ - "arm64" + "wasm32" ], - "license": "Apache-2.0", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", "cpu": [ - "x64" + "arm64" ], - "license": "Apache-2.0", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ - "x64" + "ia32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1948,442 +1645,110 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz", - "integrity": "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA==", + "node_modules/@neondatabase/serverless": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@neondatabase/serverless/-/serverless-0.10.4.tgz", + "integrity": "sha512-2nZuh3VUO9voBauuh+IGYRhGU/MskWHt1IuZvHcJw6GLjDgtqj/KViKo7SIrLdGLdot7vFbiRRw+BgEy3wT9HA==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.2.1", - "express-rate-limit": "^8.2.1", - "hono": "^4.11.4", - "jose": "^6.1.3", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - }, - "zod": { - "optional": false - } + "@types/pg": "8.11.6" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">= 0.6" + "node": ">= 8" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 8" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", "engines": { - "node": ">=6.6.0" + "node": ">= 8" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/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/@modelcontextprotocol/sdk/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/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/@modelcontextprotocol/sdk/node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@neondatabase/serverless": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@neondatabase/serverless/-/serverless-0.10.4.tgz", - "integrity": "sha512-2nZuh3VUO9voBauuh+IGYRhGU/MskWHt1IuZvHcJw6GLjDgtqj/KViKo7SIrLdGLdot7vFbiRRw+BgEy3wT9HA==", - "license": "MIT", - "dependencies": { - "@types/pg": "8.11.6" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "optional": true, "engines": { - "node": ">= 8" + "node": ">=14" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } + "license": "MIT" }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" + "kleur": "^4.1.5" } }, - "node_modules/@notionhq/client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@notionhq/client/-/client-2.3.0.tgz", - "integrity": "sha512-l7WqTCpQqC+HibkB9chghONQTYcxNQT0/rOJemBfmuKQRTu2vuV8B3yA395iKaUdDo7HI+0KvQaz9687Xskzkw==", + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/node-fetch": "^2.5.10", - "node-fetch": "^2.6.1" - }, - "engines": { - "node": ">=12" + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@poppinss/dumper/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=14" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", "dev": true, "license": "MIT" }, @@ -4430,11 +3795,25 @@ "win32" ] }, - "node_modules/@stablelib/base64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", - "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", - "license": "MIT" + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz", + "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/@standard-schema/spec": { "version": "1.1.0", @@ -4958,15 +4337,6 @@ "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, "node_modules/@transloadit/prettier-bytes": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.3.5.tgz", @@ -5025,23 +4395,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/caseless": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", - "license": "MIT" - }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -5053,28 +4406,6 @@ "assertion-error": "^2.0.1" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-pg-simple": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/connect-pg-simple/-/connect-pg-simple-7.0.3.tgz", - "integrity": "sha512-NGCy9WBlW2bw+J/QlLnFZ9WjoGs6tMo3LAut6mY4kK+XHzue//lpNVpAvYRpIwM969vBRAM2Re0izUvV6kt+NA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/express-session": "*", - "@types/pg": "*" - } - }, "node_modules/@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", @@ -5152,171 +4483,42 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, + "node_modules/@types/node": { + "version": "20.16.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz", + "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==", "license": "MIT", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "undici-types": "~6.19.2" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "dev": true, + "node_modules/@types/pg": { + "version": "8.11.6", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.6.tgz", + "integrity": "sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==", "license": "MIT", "dependencies": { "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "pg-protocol": "*", + "pg-types": "^4.0.1" } }, - "node_modules/@types/express-session": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.2.tgz", - "integrity": "sha512-k+I0BxwVXsnEU2hV77cCobC08kIsn4y44C3gC0b46uxZVMaXA04lSPgRLR/bSL2w0t0ShJiG8o4jPzRG/nscFg==", + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "dev": true, "license": "MIT", "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/memoizee": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/@types/memoizee/-/memoizee-0.4.12.tgz", - "integrity": "sha512-EdtpwNYNhe3kZ+4TlXj/++pvBoU0KdrAICMzgI7vjWgu9sIvvUhu9XR8Ks4L6Wh3sxpZ22wkZR7yCLAqUjnZuQ==", - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.16.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz", - "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.4" - } - }, - "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/passport": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz", - "integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/passport-local": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/@types/passport-local/-/passport-local-1.0.38.tgz", - "integrity": "sha512-nsrW4A963lYE7lNTv9cr5WmiUD1ibYJvWrpE13oxApFsRt77b0RdtZvKbCdNIY4v/QZ6TRQWaDDEwV1kCTmcXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*", - "@types/passport-strategy": "*" - } - }, - "node_modules/@types/passport-strategy": { - "version": "0.2.38", - "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", - "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "node_modules/@types/pg": { - "version": "8.11.6", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.6.tgz", - "integrity": "sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^4.0.1" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/qs": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", - "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" + "@types/prop-types": "*", + "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { @@ -5329,63 +4531,12 @@ "@types/react": "*" } }, - "node_modules/@types/request": { - "version": "2.48.13", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", - "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", - "license": "MIT", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.5" - } - }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "license": "MIT" }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@uppy/aws-s3": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/@uppy/aws-s3/-/aws-s3-4.3.2.tgz", @@ -6213,73 +5364,16 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 14" } }, - "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "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/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -6356,21 +5450,6 @@ "node": ">= 0.4" } }, - "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/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -6400,30 +5479,6 @@ "dev": true, "license": "MIT" }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "license": "MIT", - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "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/autoprefixer": { "version": "10.4.20", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", @@ -6462,33 +5517,6 @@ "postcss": "^8.1.0" } }, - "node_modules/axios": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6496,26 +5524,6 @@ "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/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -6526,15 +5534,6 @@ "require-from-string": "^2.0.2" } }, - "node_modules/bignumber.js": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", - "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -6548,74 +5547,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/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/body-parser/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/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, "license": "MIT" }, - "node_modules/body-parser/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/brace-expansion": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", @@ -6672,12 +5610,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "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/bufferutil": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz", @@ -6692,44 +5624,6 @@ "node": ">=6.14.2" } }, - "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/camelcase": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", @@ -6869,12 +5763,106 @@ "node": ">=0.10" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "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": ">=6" + "node": ">=12" + } + }, + "node_modules/cliui/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/cliui/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/cliui/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/cliui/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/cliui/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/cliui/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/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" } }, "node_modules/cmdk": { @@ -6912,24 +5900,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "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==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -6940,74 +5910,100 @@ "node": ">= 6" } }, - "node_modules/connect-pg-simple": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/connect-pg-simple/-/connect-pg-simple-10.0.0.tgz", - "integrity": "sha512-pBGVazlqiMrackzCr0eKhn4LO5trJXsOX0nQoey9wCOayh80MYtThCbq8eoLsjpiWgiok/h+1/uti9/2/Una8A==", + "node_modules/concurrently": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", + "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", + "dev": true, "license": "MIT", "dependencies": { - "pg": "^8.12.0" + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.8.3", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=22.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "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==", + "node_modules/concurrently/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": { - "safe-buffer": "5.2.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/concurrently/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": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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==", + "node_modules/concurrently/node_modules/chalk/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" - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "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/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/concurrently/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": { - "object-assign": "^4", - "vary": "^1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "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/cropperjs": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz", @@ -7018,6 +6014,7 @@ "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", @@ -7098,6 +6095,7 @@ "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", @@ -7228,15 +6226,6 @@ "node": ">=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/data-urls": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", @@ -7298,19 +6287,11 @@ "url": "https://github.com/sponsors/kossnocorp" } }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "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" @@ -7337,24 +6318,6 @@ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", "license": "MIT" }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "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/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -7364,21 +6327,12 @@ "node": ">=6" } }, - "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.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=8" } @@ -7430,28 +6384,6 @@ "csstype": "^3.0.2" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "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", @@ -7753,32 +6685,6 @@ "zod": ">=3.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/duplexify": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", - "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.2" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -7786,21 +6692,6 @@ "dev": true, "license": "MIT" }, - "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.51", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.51.tgz", @@ -7840,24 +6731,6 @@ "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/enhanced-resolve": { "version": "5.20.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", @@ -7885,22 +6758,14 @@ "url": "https://github.com/fb55/entities?sponsor=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==", + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, "node_modules/es-module-lexer": { @@ -7910,37 +6775,11 @@ "dev": true, "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/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==", - "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/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": { @@ -7957,6 +6796,7 @@ "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", @@ -7968,6 +6808,7 @@ "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", @@ -7981,6 +6822,7 @@ "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", @@ -8394,16 +7236,11 @@ "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/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", @@ -8425,61 +7262,23 @@ "@types/estree": "^1.0.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/event-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/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/exifr": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz", @@ -8496,165 +7295,16 @@ "node": ">=12.0.0" } }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.3.0.tgz", - "integrity": "sha512-KJzBawY6fB9FiZGdE/0aftepZ91YlaGIrV8vgblRM3J8X+dHx/aiowJWwkx6LIGyuqGiANsjSwwrbb8mifOJ4Q==", - "license": "MIT", - "dependencies": { - "ip-address": "10.1.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" - } - }, - "node_modules/express-session": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.19.0.tgz", - "integrity": "sha512-0csaMkGq+vaiZTmSMMGkfdCOabYv192VbytFypcvI0MANrp+4i/7yEkJ0sbAEhycQjntaKGzYfjfXQyVb7BHMA==", - "license": "MIT", - "dependencies": { - "cookie": "~0.7.2", - "cookie-signature": "~1.0.7", - "debug": "~2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.1.0", - "parseurl": "~1.3.3", - "safe-buffer": "~5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-session/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/express-session/node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "license": "MIT" - }, - "node_modules/express-session/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/express-session/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/express/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/express/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/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/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-copy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", - "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-equals": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", @@ -8693,61 +7343,6 @@ "node": ">= 6" } }, - "node_modules/fast-redact": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", - "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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==", - "license": "MIT" - }, - "node_modules/fast-sha256": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", - "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", - "license": "Unlicense" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fast-xml-parser": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz", - "integrity": "sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -8758,29 +7353,6 @@ "reusify": "^1.0.4" } }, - "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/fflate": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", @@ -8801,39 +7373,6 @@ "node": ">=8" } }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "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.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -8841,26 +7380,6 @@ "dev": true, "license": "ISC" }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -8878,44 +7397,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", - "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.35", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.12" - } - }, - "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/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/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -8957,15 +7438,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.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -8992,86 +7464,12 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gaxios": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", - "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/gaxios/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/gcp-metadata": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.1.tgz", - "integrity": "sha512-UcO3kefx6dCcZkgcTGgVOTFb7b1LlQ02hY1omMjjrrBzkajRMCFgYOjs7J71WqnuG1k2b+9ppGL7FsOfhZMQKQ==", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^7.0.0", - "google-logging-utils": "^1.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gcp-metadata/node_modules/gaxios": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.1.tgz", - "integrity": "sha512-Odju3uBUJyVCkW64nLD4wKLhbh93bh6vIg/ZIXkWiLPBrdgtc65+tls/qml+un3pr6JqYVFDZbbmLDQT68rTOQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gcp-metadata/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/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -9082,28 +7480,14 @@ "node": ">=6.9.0" } }, - "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" - }, + "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": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-nonce": { @@ -9114,32 +7498,6 @@ "node": ">=6" } }, - "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-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "node_modules/glob": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", @@ -9181,128 +7539,12 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "license": "BSD-2-Clause" }, - "node_modules/google-auth-library": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.2.1.tgz", - "integrity": "sha512-HMxFl2NfeHYnaL1HoRIN1XgorKS+6CDaM+z9LSSN+i/nKDDL4KFFEWogMXu7jV4HZQy2MsxpY+wA5XIf3w410A==", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^7.0.0", - "gcp-metadata": "^7.0.0", - "google-logging-utils": "^1.0.0", - "gtoken": "^8.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/google-auth-library/node_modules/gaxios": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.1.tgz", - "integrity": "sha512-Odju3uBUJyVCkW64nLD4wKLhbh93bh6vIg/ZIXkWiLPBrdgtc65+tls/qml+un3pr6JqYVFDZbbmLDQT68rTOQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/google-auth-library/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/google-logging-utils": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.1.tgz", - "integrity": "sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "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/gtoken": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", - "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", - "license": "MIT", - "dependencies": { - "gaxios": "^7.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gtoken/node_modules/gaxios": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.1.tgz", - "integrity": "sha512-Odju3uBUJyVCkW64nLD4wKLhbh93bh6vIg/ZIXkWiLPBrdgtc65+tls/qml+un3pr6JqYVFDZbbmLDQT68rTOQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/gtoken/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/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/hanji": { "version": "0.0.5", @@ -9325,37 +7567,11 @@ "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==", - "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.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9371,12 +7587,6 @@ "dev": true, "license": "MIT" }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" - }, "node_modules/hono": { "version": "4.12.18", "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.18.tgz", @@ -9399,22 +7609,6 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/html-entities": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -9422,52 +7616,11 @@ "dev": true, "license": "MIT" }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.2", @@ -9477,18 +7630,6 @@ "node": ">= 14" } }, - "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/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -9515,6 +7656,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, "license": "ISC" }, "node_modules/input-otp": { @@ -9535,24 +7677,6 @@ "node": ">=12" } }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "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-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -9654,24 +7778,14 @@ "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-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "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": { @@ -9763,15 +7877,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/js-cookie": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", @@ -9893,15 +7998,6 @@ "node": ">=6" } }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, "node_modules/json-diff": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.9.0.tgz", @@ -9920,18 +8016,6 @@ "node": "*" } }, - "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/json-schema-typed": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", - "license": "BSD-2-Clause" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9945,25 +8029,14 @@ "node": ">=6" } }, - "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==", + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, "license": "MIT", - "dependencies": { - "jwa": "^2.0.1", - "safe-buffer": "^5.0.1" + "engines": { + "node": ">=6" } }, "node_modules/lightningcss": { @@ -10299,15 +8372,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -10322,6 +8386,7 @@ "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" @@ -10396,27 +8461,6 @@ "node": ">=10" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/mdn-data": { "version": "2.27.1", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", @@ -10424,19 +8468,11 @@ "dev": true, "license": "CC0-1.0" }, - "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/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", @@ -10452,44 +8488,6 @@ "node": ">=0.12" } }, - "node_modules/memorystore": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/memorystore/-/memorystore-1.6.7.tgz", - "integrity": "sha512-OZnmNY/NDrKohPQ+hxp0muBcBKrzKNtHr55DbqSx9hLsYVNnomSAMRAtI7R64t3gf3ID7tHQA7mG4oL3Hu9hdw==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.0", - "lru-cache": "^4.0.3" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/memorystore/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/memorystore/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "license": "ISC" - }, - "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/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -10500,15 +8498,6 @@ "node": ">= 8" } }, - "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", @@ -10523,27 +8512,6 @@ "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-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", @@ -10553,18 +8521,6 @@ "wildcard": "^1.1.0" } }, - "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/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -10575,29 +8531,63 @@ "node": ">=4" } }, - "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "node_modules/miniflare": { + "version": "4.20260515.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260515.0.tgz", + "integrity": "sha512-2j0oQWizk1Eu4Cm8tDX7Z+Nsjd0nebIj1TQcQ+Oy1QKeo0Ay9+bdn8wfLAtOj9znDCybDCUlnS1+nYvKXEdfNg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.2" + "@cspotcode/source-map-support": "0.8.1", + "sharp": "^0.34.5", + "undici": "7.24.8", + "workerd": "1.20260515.1", + "ws": "8.18.0", + "youch": "4.1.0-beta.10" }, - "engines": { - "node": ">=16 || 14 >=14.17" + "bin": { + "miniflare": "bootstrap.js" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=22.0.0" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/miniflare/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minipass": { @@ -10640,6 +8630,7 @@ "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/mz": { @@ -10679,15 +8670,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/next-themes": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", @@ -10701,58 +8683,9 @@ "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/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "license": "MIT", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "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": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-gyp-build": { "version": "4.8.3", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", @@ -10792,15 +8725,6 @@ "node": ">=0.10.0" } }, - "node_modules/oauth4webapi": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.6.1.tgz", - "integrity": "sha512-b39+drVyA4aNUptFOhkkmGWnG/BE7dT29SW/8PVYElqp7j/DBqzm5SS1G+MUD07XlTcBOAG+6Cb/35Cx2kHIuQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10820,18 +8744,6 @@ "node": ">= 6" } }, - "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/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -10849,40 +8761,11 @@ ], "license": "MIT" }, - "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/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/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -10909,34 +8792,6 @@ } } }, - "node_modules/openid-client": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.6.3.tgz", - "integrity": "sha512-sYYFJsyN21bjf/QepIU/t6w22tEUT+rYVPf1VZOSQwC+s1hAkyZpvAbFNLMrnrYMS/H74MctEHna2jPLvWbkCA==", - "license": "MIT", - "dependencies": { - "jose": "^6.0.12", - "oauth4webapi": "^3.6.1" - }, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-queue": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", @@ -11008,19 +8863,11 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "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-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" @@ -11057,12 +8904,6 @@ "dev": true, "license": "ISC" }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -11070,46 +8911,6 @@ "dev": true, "license": "MIT" }, - "node_modules/pg": { - "version": "8.13.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", - "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", - "license": "MIT", - "dependencies": { - "pg-connection-string": "^2.7.0", - "pg-pool": "^3.7.0", - "pg-protocol": "^1.7.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "optionalDependencies": { - "pg-cloudflare": "^1.1.1" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-cloudflare": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "license": "MIT", - "optional": true - }, - "node_modules/pg-connection-string": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", - "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", - "license": "MIT" - }, "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", @@ -11128,15 +8929,6 @@ "node": ">=4" } }, - "node_modules/pg-pool": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", - "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", - "license": "MIT", - "peerDependencies": { - "pg": ">=8.0" - } - }, "node_modules/pg-protocol": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", @@ -11161,70 +8953,6 @@ "node": ">=10" } }, - "node_modules/pg/node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "license": "MIT", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pg/node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pg/node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pg/node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pg/node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "license": "MIT", - "dependencies": { - "split2": "^4.1.0" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -11255,67 +8983,6 @@ "node": ">=0.10.0" } }, - "node_modules/pino": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.9.0.tgz", - "integrity": "sha512-zxsRIQG9HzG+jEljmvmZupOMDUQ0Jpj0yAgE28jQvvrdYTlEaiGwelJpdndMl/MBuRr70heIj83QyqJUWaU8mQ==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "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-pretty": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.1.tgz", - "integrity": "sha512-TNNEOg0eA0u+/WuqH0MH0Xui7uqVk9D74ESOpjtebSQYbNWJk/dIxCXIxFsNfeN53JmtWqYHP2OrIZjT/CBEnA==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^2.0.0", - "pump": "^3.0.0", - "secure-json-parse": "^4.0.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^5.0.2" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-std-serializers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", - "license": "MIT" - }, "node_modules/pirates": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", @@ -11326,15 +8993,6 @@ "node": ">= 6" } }, - "node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -11610,22 +9268,6 @@ "dev": true, "license": "MIT" }, - "node_modules/process-warning": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", - "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -11641,41 +9283,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "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/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "license": "ISC" - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -11686,21 +9293,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11722,74 +9314,6 @@ ], "license": "MIT" }, - "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/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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/raw-body/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/raw-body/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/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -11982,20 +9506,6 @@ "pify": "^2.3.0" } }, - "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/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -12009,15 +9519,6 @@ "node": ">=8.10.0" } }, - "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/recharts": { "version": "2.15.2", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.2.tgz", @@ -12077,10 +9578,21 @@ "node": ">=8" } }, + "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/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==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12104,16 +9616,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -12123,20 +9625,6 @@ "node": ">= 4" } }, - "node_modules/retry-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", - "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", - "license": "MIT", - "dependencies": { - "@types/request": "^2.48.8", - "extend": "^3.0.2", - "teeny-request": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -12193,38 +9681,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/router/node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, - "node_modules/router/node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -12249,41 +9705,16 @@ "queue-microtask": "^1.2.2" } }, - "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-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/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -12306,22 +9737,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/secure-json-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz", - "integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -12332,361 +9747,508 @@ "semver": "bin/semver.js" } }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "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/shallow-equal": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz", "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==", "license": "MIT" }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "url": "https://opencollective.com/libvips" }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/sharp/node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "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" + "url": "https://opencollective.com/libvips" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, - "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" - }, + "node_modules/sharp/node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, - "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/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/sharp/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/libvips" } }, - "node_modules/sirv": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "node_modules/sharp/node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "node_modules/sharp/node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "node_modules/sharp/node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/snakecase-keys": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-8.0.1.tgz", - "integrity": "sha512-Sj51kE1zC7zh6TDlNNz0/Jn1n5HiHdoQErxO8jLtnyrkJW/M5PrI7x05uDgY3BO7OUQYKCvmeMurW6BPUdwEOw==", - "license": "MIT", - "dependencies": { - "map-obj": "^4.1.0", - "snake-case": "^3.0.4", - "type-fest": "^4.15.0" - }, - "engines": { - "node": ">=18" + "node_modules/sharp/node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/sonic-boom": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", - "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" + "node_modules/sharp/node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "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==", + "node_modules/sharp/node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", + "node_modules/sharp/node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 10.x" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" } }, - "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==", + "node_modules/sharp/node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/standardwebhooks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", - "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==", - "license": "MIT", - "dependencies": { - "@stablelib/base64": "^1.0.0", - "fast-sha256": "^1.3.0" + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", + "node_modules/sharp/node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" } }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "license": "MIT" - }, - "node_modules/stream-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", - "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", - "license": "MIT", - "dependencies": { - "stubs": "^3.0.0" + "node_modules/sharp/node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", - "license": "MIT" - }, - "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/sharp/node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/sharp/node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/libvips" } }, - "node_modules/string-width-cjs": { - "name": "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==", + "node_modules/sharp/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "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/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "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/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/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": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "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/string-width-cjs/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", @@ -12767,36 +10329,6 @@ "node": ">=8" } }, - "node_modules/strip-json-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", - "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/stubs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", - "license": "MIT" - }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -12934,60 +10466,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/teeny-request": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", - "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", - "license": "Apache-2.0", - "dependencies": { - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.9", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/teeny-request/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/teeny-request/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/teeny-request/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/test-exclude": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", @@ -13026,19 +10504,11 @@ "node": ">=0.8" } }, - "node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "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", @@ -13162,15 +10632,6 @@ "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/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -13194,11 +10655,15 @@ "node": ">=16" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } }, "node_modules/ts-interface-checker": { "version": "0.1.13", @@ -13213,26 +10678,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tsx": { - "version": "4.20.5", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", - "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, "node_modules/tw-animate-css": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.2.5.tgz", @@ -13245,33 +10690,9 @@ "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/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "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/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", @@ -13286,22 +10707,10 @@ "node": ">=14.17" } }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "license": "MIT", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/undici": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", - "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.8.tgz", + "integrity": "sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ==", "dev": true, "license": "MIT", "engines": { @@ -13314,13 +10723,14 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "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==", + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8" + "dependencies": { + "pathe": "^2.0.3" } }, "node_modules/update-browserslist-db": { @@ -13408,35 +10818,9 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, "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/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/vaul": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", @@ -13695,150 +11079,673 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/vitest/node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "node_modules/vitest/node_modules/@vitest/utils": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest/node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "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/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/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", + "license": "MIT" + }, + "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/workerd": { + "version": "1.20260515.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260515.1.tgz", + "integrity": "sha512-MjKOJLcvU45xXedQowvuiHtJTxu4WTHYQeIlF7YmjuqhiI6dImTFxWCEoRQHiskztxuVSNEmdO7/0UfDu6OMnQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260515.1", + "@cloudflare/workerd-darwin-arm64": "1.20260515.1", + "@cloudflare/workerd-linux-64": "1.20260515.1", + "@cloudflare/workerd-linux-arm64": "1.20260515.1", + "@cloudflare/workerd-windows-64": "1.20260515.1" + } + }, + "node_modules/wouter": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/wouter/-/wouter-3.3.5.tgz", + "integrity": "sha512-bx3fLQAMn+EhYbBdY3W1gw9ZfO/uchudxYMwOIBzF3HVgqNEEIT199vEoh7FLTC0Vz5+rpMO6NdFsOkGX1QQCw==", + "license": "Unlicense", + "dependencies": { + "mitt": "^3.0.1", + "regexparam": "^3.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/wrangler": { + "version": "4.92.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.92.0.tgz", + "integrity": "sha512-/DKpQHPxkuZbQsO9dFW2700VTD/4DSZMHjy92fO/frNoDRi/zQsFCAd2ONCV6TGqcUoXcP3D8Bo2gj/L4M0qQQ==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.5.0", + "@cloudflare/unenv-preset": "2.16.1", + "blake3-wasm": "2.1.5", + "esbuild": "0.27.3", + "miniflare": "4.20260515.0", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20260515.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=22.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20260515.1" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/wrangler/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/wrangler/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=18" } }, - "node_modules/vitest/node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "node_modules/wrangler/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "xml-name-validator": "^5.0.0" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { "node": ">=18" } }, - "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==", + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-mimetype": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", - "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=20" + "node": ">=18" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 8" + "node": ">=18" } }, - "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==", + "node_modules/wrangler/node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, "bin": { - "why-is-node-running": "cli.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=8" - } - }, - "node_modules/wildcard": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", - "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", - "license": "MIT" - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/wrangler/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true, "license": "MIT" }, - "node_modules/wouter": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/wouter/-/wouter-3.3.5.tgz", - "integrity": "sha512-bx3fLQAMn+EhYbBdY3W1gw9ZfO/uchudxYMwOIBzF3HVgqNEEIT199vEoh7FLTC0Vz5+rpMO6NdFsOkGX1QQCw==", - "license": "Unlicense", - "dependencies": { - "mitt": "^3.0.1", - "regexparam": "^3.0.0", - "use-sync-external-store": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -13941,29 +11848,9 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, "license": "ISC" }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -13981,13 +11868,14 @@ "dev": true, "license": "MIT" }, - "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", + "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": ">=0.4" + "node": ">=10" } }, "node_modules/yallist": { @@ -14010,16 +11898,117 @@ "node": ">= 14" } }, - "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==", + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "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": ">=10" + "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/yargs/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/yargs/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/yargs/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/yargs/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/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/youch/node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/zod": { @@ -14031,15 +12020,6 @@ "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - }, "node_modules/zod-validation-error": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", diff --git a/package.json b/package.json index 03b0e4a..b072b00 100644 --- a/package.json +++ b/package.json @@ -17,37 +17,31 @@ "ownership-proof", "dashboard", "react", - "express", + "hono", + "cloudflare-workers", "drizzle", "neon" ], "scripts": { - "dev": "NODE_ENV=development tsx server/index.ts", - "build": "vite build && esbuild server/index.ts --platform=node --packages=external --bundle --format=esm --outdir=dist", - "start": "NODE_ENV=production node dist/index.js", + "dev": "concurrently -n vite,worker -c green,blue \"vite\" \"wrangler dev\"", + "dev:api": "wrangler dev", + "dev:web": "vite", + "build": "vite build", "check": "tsc", + "deploy": "wrangler deploy --env production", "db:push": "drizzle-kit push", "install-github-app": "node scripts/install-github-app.js", "test:github-app": "node scripts/test-github-app.js", "test": "vitest", "test:ui": "vitest --ui", - "test:coverage": "vitest --coverage", - "test:working": "vitest run server/__tests__/simple.test.ts server/__tests__/integration/api.test.ts client/src/__tests__/components/SimpleButton.test.tsx" + "test:coverage": "vitest --coverage" }, "dependencies": { - "@anthropic-ai/claude-code": "^2.1.7", - "@chittyapps/chittycloude-mcp": "^1.0.0", - "@clerk/backend": "^1.0.0", "@clerk/clerk-react": "^5.0.0", - "@clerk/clerk-sdk-node": "^5.0.0", - "@clerk/express": "^2.0.1", - "@clerk/types": "^4.0.0", - "@google-cloud/storage": "^7.16.0", "@hono/zod-validator": "^0.8.0", "@hookform/resolvers": "^3.10.0", "@jridgewell/trace-mapping": "^0.3.25", "@neondatabase/serverless": "^0.10.4", - "@notionhq/client": "^2.2.14", "@radix-ui/react-accordion": "^1.2.4", "@radix-ui/react-alert-dialog": "^1.1.7", "@radix-ui/react-aspect-ratio": "^1.1.3", @@ -76,7 +70,6 @@ "@radix-ui/react-toggle-group": "^1.1.3", "@radix-ui/react-tooltip": "^1.2.8", "@tanstack/react-query": "^5.60.5", - "@types/memoizee": "^0.4.12", "@uppy/aws-s3": "^4.3.2", "@uppy/core": "^5.2.0", "@uppy/dashboard": "^4.4.3", @@ -87,24 +80,17 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "connect-pg-simple": "^10.0.0", "date-fns": "^3.6.0", "drizzle-orm": "^0.39.1", "drizzle-zod": "^0.7.0", "embla-carousel-react": "^8.6.0", - "express": "^4.22.1", - "express-session": "^1.19.0", "framer-motion": "^11.13.1", - "google-auth-library": "^10.2.1", "hono": "^4.12.18", "input-otp": "^1.4.2", "jose": "^6.2.3", "lucide-react": "^0.453.0", - "memoizee": "^0.4.17", - "memorystore": "^1.6.7", "next-themes": "^0.4.6", "openai": "^5.12.0", - "openid-client": "^6.6.3", "postgres": "^3.4.9", "react": "^18.3.1", "react-day-picker": "^8.10.1", @@ -118,39 +104,33 @@ "tw-animate-css": "^1.2.5", "vaul": "^1.1.2", "wouter": "^3.3.5", - "ws": "^8.18.0", "zod": "^3.24.2", "zod-validation-error": "^3.4.0" }, "devDependencies": { + "@cloudflare/workers-types": "^4.20260517.1", "@tailwindcss/typography": "^0.5.15", "@tailwindcss/vite": "^4.2.1", "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^6.8.0", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", - "@types/connect-pg-simple": "^7.0.3", - "@types/express": "4.17.21", - "@types/express-session": "^1.18.2", "@types/node": "20.16.11", - "@types/passport": "^1.0.16", - "@types/passport-local": "^1.0.38", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.1", - "@types/ws": "^8.5.13", "@vitejs/plugin-react": "^4.3.2", "@vitest/coverage-v8": "^3.2.4", "@vitest/ui": "^3.2.4", "autoprefixer": "^10.4.20", + "concurrently": "^9.0.0", "drizzle-kit": "^0.18.1", - "esbuild": "^0.25.12", "jsdom": "^28.1.0", "postcss": "^8.4.47", "tailwindcss": "^3.4.17", - "tsx": "^4.19.1", "typescript": "5.6.3", "vite": "^7.1.11", - "vitest": "^4.0.18" + "vitest": "^4.0.18", + "wrangler": "^4.0.0" }, "optionalDependencies": { "bufferutil": "^4.0.8" diff --git a/scripts/notion-sync.js b/scripts/notion-sync.js deleted file mode 100644 index 6de700b..0000000 --- a/scripts/notion-sync.js +++ /dev/null @@ -1,286 +0,0 @@ -#!/usr/bin/env node - -/** - * Notion Command Center Sync Script - * Syncs ChittyAssets data and metadata to Notion Command Center - */ - -import { Client } from '@notionhq/client'; -import { promises as fs } from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -// Initialize Notion client -const notion = new Client({ - auth: process.env.NOTION_API_KEY, -}); - -const databaseId = process.env.NOTION_DATABASE_ID; - -/** - * Main sync function - */ -async function syncToNotion() { - console.log('🚀 Starting Notion Command Center Sync...'); - - try { - // Collect repository metadata - const metadata = await collectMetadata(); - - // Sync repository information - await syncRepositoryInfo(metadata); - - // Sync recent commits - await syncRecentCommits(); - - // Sync asset statistics - await syncAssetStats(); - - // Sync ChittyAuth integration status - await syncAuthStatus(); - - // Sync ecosystem services status - await syncEcosystemStatus(); - - console.log('✅ Notion sync completed successfully'); - } catch (error) { - console.error('❌ Notion sync failed:', error.message); - console.error(error.stack); - process.exit(1); - } -} - -/** - * Collect repository metadata - */ -async function collectMetadata() { - console.log('📊 Collecting repository metadata...'); - - const packageJson = JSON.parse( - await fs.readFile(path.join(__dirname, '..', 'package.json'), 'utf-8') - ); - - // Get git information - const gitInfo = { - branch: process.env.GITHUB_REF_NAME || 'main', - sha: process.env.GITHUB_SHA || 'unknown', - actor: process.env.GITHUB_ACTOR || 'unknown', - runNumber: process.env.GITHUB_RUN_NUMBER || '0', - runId: process.env.GITHUB_RUN_ID || '0', - }; - - return { - name: packageJson.name, - version: packageJson.version, - description: packageJson.description, - dependencies: Object.keys(packageJson.dependencies || {}).length, - devDependencies: Object.keys(packageJson.devDependencies || {}).length, - ...gitInfo, - timestamp: new Date().toISOString(), - }; -} - -/** - * Sync repository information to Notion - */ -async function syncRepositoryInfo(metadata) { - console.log('📝 Syncing repository information...'); - - try { - // Search for existing page or create new one - const response = await notion.databases.query({ - database_id: databaseId, - filter: { - property: 'Repository', - title: { - equals: 'ChittyAssets', - }, - }, - }); - - const properties = { - 'Repository': { - title: [ - { - text: { - content: 'ChittyAssets', - }, - }, - ], - }, - 'Version': { - rich_text: [ - { - text: { - content: metadata.version, - }, - }, - ], - }, - 'Description': { - rich_text: [ - { - text: { - content: metadata.description, - }, - }, - ], - }, - 'Last Sync': { - date: { - start: metadata.timestamp, - }, - }, - 'Status': { - select: { - name: 'Active', - }, - }, - 'Dependencies': { - number: metadata.dependencies, - }, - 'Branch': { - rich_text: [ - { - text: { - content: metadata.branch, - }, - }, - ], - }, - 'Last Commit': { - rich_text: [ - { - text: { - content: metadata.sha.substring(0, 7), - }, - }, - ], - }, - }; - - if (response.results.length > 0) { - // Update existing page - await notion.pages.update({ - page_id: response.results[0].id, - properties, - }); - console.log('📝 Updated existing repository page'); - } else { - // Create new page - await notion.pages.create({ - parent: { database_id: databaseId }, - properties, - }); - console.log('📝 Created new repository page'); - } - } catch (error) { - console.error('Failed to sync repository info:', error.message); - throw error; - } -} - -/** - * Sync recent commits - */ -async function syncRecentCommits() { - console.log('🔄 Syncing recent commits...'); - - // This would typically fetch from GitHub API - // For now, we'll use environment variables - const commitInfo = { - sha: process.env.GITHUB_SHA || 'unknown', - message: process.env.GITHUB_EVENT_NAME === 'push' - ? 'Latest push to ' + (process.env.GITHUB_REF_NAME || 'main') - : 'Pull request update', - author: process.env.GITHUB_ACTOR || 'unknown', - timestamp: new Date().toISOString(), - }; - - console.log(`📝 Latest commit: ${commitInfo.sha.substring(0, 7)} by ${commitInfo.author}`); -} - -/** - * Sync asset statistics - */ -async function syncAssetStats() { - console.log('📈 Syncing asset statistics...'); - - // Count various file types - const stats = { - totalFiles: 0, - jsFiles: 0, - tsFiles: 0, - components: 0, - tests: 0, - }; - - async function countFiles(dir) { - try { - const entries = await fs.readdir(dir, { withFileTypes: true }); - - for (const entry of entries) { - const fullPath = path.join(dir, entry.name); - - if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') { - await countFiles(fullPath); - } else if (entry.isFile()) { - stats.totalFiles++; - if (entry.name.endsWith('.js')) stats.jsFiles++; - if (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) stats.tsFiles++; - if (entry.name.endsWith('.tsx') && fullPath.includes('components')) stats.components++; - if (entry.name.includes('.test.') || entry.name.includes('.spec.')) stats.tests++; - } - } - } catch (error) { - // Ignore errors for directories we can't read - } - } - - await countFiles(path.join(__dirname, '..')); - - console.log(`📊 Stats: ${stats.totalFiles} files, ${stats.tsFiles} TypeScript, ${stats.components} components`); -} - -/** - * Sync ChittyAuth status - */ -async function syncAuthStatus() { - console.log('🔐 Syncing ChittyAuth status...'); - - const authStatus = { - provider: 'Clerk', - chittyIdEnabled: true, - chittyVerifyEnabled: true, - mfaSupported: true, - verificationMethods: ['email', 'phone', 'document'], - }; - - console.log('✅ ChittyAuth integration active'); -} - -/** - * Sync ecosystem services status - */ -async function syncEcosystemStatus() { - console.log('🌐 Syncing ecosystem status...'); - - const services = [ - { name: 'ChittyID', status: 'operational' }, - { name: 'ChittyAuth', status: 'operational' }, - { name: 'ChittyChain', status: 'operational' }, - { name: 'ChittyRegistry', status: 'operational' }, - { name: 'ChittyAssets', status: 'operational' }, - ]; - - console.log(`✅ ${services.length} ecosystem services operational`); -} - -// Run sync -syncToNotion().catch((error) => { - console.error('Fatal error:', error); - process.exit(1); -}); \ No newline at end of file diff --git a/scripts/update-sync-status.js b/scripts/update-sync-status.js deleted file mode 100644 index 8b40a6b..0000000 --- a/scripts/update-sync-status.js +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env node - -/** - * Update Notion sync status - * Updates a status page in Notion with the latest sync results - */ - -import { Client } from '@notionhq/client'; - -// Initialize Notion client -const notion = new Client({ - auth: process.env.NOTION_API_KEY, -}); - -const statusPageId = process.env.NOTION_STATUS_PAGE_ID; - -async function updateSyncStatus(status) { - console.log(`📝 Updating sync status: ${status}`); - - try { - if (!statusPageId) { - console.warn('⚠️ NOTION_STATUS_PAGE_ID not configured, skipping status update'); - return; - } - - const emoji = status === 'success' ? '✅' : '❌'; - const statusText = status === 'success' ? 'Operational' : 'Failed'; - const color = status === 'success' ? 'green' : 'red'; - - await notion.blocks.children.append({ - block_id: statusPageId, - children: [ - { - object: 'block', - type: 'callout', - callout: { - icon: { - type: 'emoji', - emoji: emoji, - }, - color: color === 'green' ? 'green_background' : 'red_background', - rich_text: [ - { - type: 'text', - text: { - content: `ChittyAssets Sync ${statusText}`, - }, - annotations: { - bold: true, - }, - }, - { - type: 'text', - text: { - content: `\nLast update: ${new Date().toLocaleString()}`, - }, - }, - { - type: 'text', - text: { - content: `\nRun: #${process.env.GITHUB_RUN_NUMBER || 'N/A'}`, - }, - }, - { - type: 'text', - text: { - content: `\nCommit: ${(process.env.GITHUB_SHA || 'unknown').substring(0, 7)}`, - }, - }, - { - type: 'text', - text: { - content: `\nBranch: ${process.env.GITHUB_REF_NAME || 'main'}`, - }, - }, - ], - }, - }, - ], - }); - - console.log(`✅ Status updated: ${statusText}`); - } catch (error) { - console.error('Failed to update status:', error.message); - // Don't fail the workflow if status update fails - } -} - -// Get status from command line argument -const status = process.argv[2] || 'unknown'; -updateSyncStatus(status); \ No newline at end of file diff --git a/server/__tests__/aiAnalysis.test.ts b/server/__tests__/aiAnalysis.test.ts deleted file mode 100644 index 7bd6096..0000000 --- a/server/__tests__/aiAnalysis.test.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { AIAnalysisService } from '../aiAnalysis'; -import OpenAI from 'openai'; - -// Mock OpenAI -vi.mock('openai', () => ({ - default: vi.fn(() => ({ - chat: { - completions: { - create: vi.fn(), - }, - }, - })), -})); - -describe('AIAnalysisService', () => { - let aiService: AIAnalysisService; - let mockOpenAI: any; - - beforeEach(() => { - vi.clearAllMocks(); - aiService = new AIAnalysisService(); - mockOpenAI = new OpenAI(); - }); - - describe('analyzeReceipt', () => { - it('should analyze receipt and return structured data', async () => { - const mockResponse = { - choices: [{ - message: { - content: JSON.stringify({ - merchant: 'Best Buy', - amount: 299.99, - currency: 'USD', - date: '2024-01-15', - items: [ - { - description: 'Wireless Headphones', - quantity: 1, - price: 299.99, - }, - ], - taxAmount: 24.00, - confidence: 0.95, - category: 'electronics', - }), - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - const result = await aiService.analyzeReceipt('base64-image-data'); - - expect(result).toEqual({ - merchant: 'Best Buy', - amount: 299.99, - currency: 'USD', - date: '2024-01-15', - items: [ - { - description: 'Wireless Headphones', - quantity: 1, - price: 299.99, - }, - ], - taxAmount: 24.00, - confidence: 0.95, - category: 'electronics', - }); - - expect(mockOpenAI.chat.completions.create).toHaveBeenCalledWith({ - model: 'gpt-4o', - messages: expect.arrayContaining([ - expect.objectContaining({ - role: 'system', - }), - expect.objectContaining({ - role: 'user', - content: expect.arrayContaining([ - expect.objectContaining({ - type: 'text', - }), - expect.objectContaining({ - type: 'image_url', - image_url: { - url: 'data:image/jpeg;base64,base64-image-data', - }, - }), - ]), - }), - ]), - max_tokens: 1000, - temperature: 0.1, - }); - }); - - it('should handle invalid JSON response', async () => { - const mockResponse = { - choices: [{ - message: { - content: 'Invalid JSON response', - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - await expect(aiService.analyzeReceipt('base64-image-data')).rejects.toThrow(); - }); - - it('should handle OpenAI API errors', async () => { - mockOpenAI.chat.completions.create.mockRejectedValue(new Error('API Error')); - - await expect(aiService.analyzeReceipt('base64-image-data')).rejects.toThrow('API Error'); - }); - }); - - describe('analyzeDocument', () => { - it('should analyze document and extract key information', async () => { - const mockResponse = { - choices: [{ - message: { - content: JSON.stringify({ - documentType: 'warranty', - keyFields: { - product: 'MacBook Pro', - warrantyPeriod: '1 year', - startDate: '2024-01-15', - coverageType: 'limited warranty', - }, - confidence: 0.92, - summary: 'One-year limited warranty for MacBook Pro starting January 15, 2024', - extractedText: 'Apple Inc. Limited Warranty MacBook Pro...', - }), - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - const result = await aiService.analyzeDocument('base64-image-data'); - - expect(result).toEqual({ - documentType: 'warranty', - keyFields: { - product: 'MacBook Pro', - warrantyPeriod: '1 year', - startDate: '2024-01-15', - coverageType: 'limited warranty', - }, - confidence: 0.92, - summary: 'One-year limited warranty for MacBook Pro starting January 15, 2024', - extractedText: 'Apple Inc. Limited Warranty MacBook Pro...', - }); - }); - }); - - describe('valuateAsset', () => { - it('should provide asset valuation with market analysis', async () => { - const mockResponse = { - choices: [{ - message: { - content: JSON.stringify({ - estimatedValue: 1200, - currency: 'USD', - confidence: 0.85, - factors: [ - 'Current market conditions', - 'Product age and condition', - 'Brand reputation', - 'Depreciation rate', - ], - marketComparisons: [ - { - source: 'eBay', - price: 1150, - similarity: 0.9, - }, - { - source: 'Amazon', - price: 1299, - similarity: 0.85, - }, - ], - }), - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - const assetDescription = 'MacBook Pro 14-inch, M1 Pro, 16GB RAM, 512GB SSD, purchased in 2023'; - const result = await aiService.valuateAsset(assetDescription, ['receipt-image', 'product-image']); - - expect(result).toEqual({ - estimatedValue: 1200, - currency: 'USD', - confidence: 0.85, - factors: [ - 'Current market conditions', - 'Product age and condition', - 'Brand reputation', - 'Depreciation rate', - ], - marketComparisons: [ - { - source: 'eBay', - price: 1150, - similarity: 0.9, - }, - { - source: 'Amazon', - price: 1299, - similarity: 0.85, - }, - ], - }); - }); - - it('should handle valuation without images', async () => { - const mockResponse = { - choices: [{ - message: { - content: JSON.stringify({ - estimatedValue: 800, - currency: 'USD', - confidence: 0.6, - factors: ['Limited information available', 'Generic market pricing'], - }), - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - const result = await aiService.valuateAsset('Generic laptop', []); - - expect(result.estimatedValue).toBe(800); - expect(result.confidence).toBe(0.6); - }); - }); - - describe('generateLegalDocument', () => { - it('should generate legal document from asset data', async () => { - const mockResponse = { - choices: [{ - message: { - content: 'ASSET OWNERSHIP AFFIDAVIT\n\nI, John Doe, hereby declare under penalty of perjury...', - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - const assetData = { - title: 'MacBook Pro', - value: 2000, - purchaseDate: '2024-01-15', - evidence: ['receipt', 'warranty'], - }; - - const result = await aiService.generateLegalDocument('ownership_affidavit', assetData); - - expect(result).toContain('ASSET OWNERSHIP AFFIDAVIT'); - expect(result).toContain('John Doe'); - expect(mockOpenAI.chat.completions.create).toHaveBeenCalledWith( - expect.objectContaining({ - model: 'gpt-4o', - messages: expect.arrayContaining([ - expect.objectContaining({ - role: 'system', - content: expect.stringContaining('legal document'), - }), - ]), - }) - ); - }); - }); - - describe('calculateTrustScore', () => { - it('should calculate trust score based on evidence', async () => { - const mockResponse = { - choices: [{ - message: { - content: JSON.stringify({ - trustScore: 85, - factors: ['High quality documentation', 'Complete evidence set'], - }), - }, - }], - }; - - mockOpenAI.chat.completions.create.mockResolvedValue(mockResponse); - - const assetData = { title: 'Test Asset', value: 1000 }; - const evidenceData = [ - { type: 'receipt', confidence: 0.95 }, - { type: 'photo', confidence: 0.9 }, - { type: 'manual', confidence: 0.85 }, - ]; - - const result = await aiService.calculateTrustScore(assetData, evidenceData); - - expect(result).toBe(85); - }); - }); -}); \ No newline at end of file diff --git a/server/__tests__/integration/api.test.ts b/server/__tests__/integration/api.test.ts deleted file mode 100644 index 6330e87..0000000 --- a/server/__tests__/integration/api.test.ts +++ /dev/null @@ -1,575 +0,0 @@ -import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest'; -import { listToolResources } from '../../toolRegistry'; - -// Simple integration test to verify API concepts -describe('API Integration Tests', () => { - it('should verify environment variables are accessible', () => { - // These should be set in our test setup - expect(process.env.NODE_ENV).toBe('test'); - expect(process.env.DATABASE_URL).toBeDefined(); - expect(process.env.SESSION_SECRET).toBeDefined(); - }); - - it('should verify mock fetch works', async () => { - // Mock a simple API response - global.fetch = vi.fn().mockResolvedValue({ - ok: true, - json: () => Promise.resolve({ status: 'success', data: 'test' }), - }); - - const response = await fetch('/api/test'); - const data = await response.json(); - - expect(response.ok).toBe(true); - expect(data.status).toBe('success'); - expect(data.data).toBe('test'); - }); - - it('should verify error handling patterns', async () => { - // Mock an API error - global.fetch = vi.fn().mockRejectedValue(new Error('Network error')); - - try { - await fetch('/api/error'); - expect.fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toBe('Network error'); - } - }); - - it('should verify async/await patterns work correctly', async () => { - const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); - - const start = Date.now(); - await delay(10); - const end = Date.now(); - - expect(end - start).toBeGreaterThanOrEqual(9); // Allow for some timing variance - }); - - it('should verify JSON serialization/deserialization', () => { - const testData = { - id: 'test-123', - name: 'Test Asset', - value: 1000.50, - active: true, - tags: ['electronics', 'valuable'], - metadata: { - source: 'test', - verified: false, - }, - }; - - const serialized = JSON.stringify(testData); - const deserialized = JSON.parse(serialized); - - expect(deserialized).toEqual(testData); - expect(typeof deserialized.value).toBe('number'); - expect(Array.isArray(deserialized.tags)).toBe(true); - }); - - it('should surface all connectors as callable tool resources', () => { - const resources = listToolResources(); - const callableIds = resources.filter(resource => resource.callable).map(resource => resource.id); - - const requiredConnectors = [ - 'cloudflare.workers.assets', - 'notion.search', - 'google.drive.search', - 'outlook.mail.search', - 'neon.metadata.search', - ]; - - requiredConnectors.forEach(connector => { - expect(callableIds).toContain(connector); - }); - }); -}); - - describe('listToolResources function', () => { - it('should return an array of tool resources', () => { - const resources = listToolResources(); - expect(Array.isArray(resources)).toBe(true); - expect(resources.length).toBeGreaterThan(0); - }); - - it('should return exactly 5 tool resources', () => { - const resources = listToolResources(); - expect(resources).toHaveLength(5); - }); - - it('should return resources with all required properties', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(resource).toHaveProperty('id'); - expect(resource).toHaveProperty('name'); - expect(resource).toHaveProperty('provider'); - expect(resource).toHaveProperty('description'); - expect(resource).toHaveProperty('category'); - expect(resource).toHaveProperty('callable'); - expect(resource).toHaveProperty('capabilities'); - }); - }); - - it('should have all resources marked as callable', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(resource.callable).toBe(true); - }); - }); - - it('should return resources with non-empty string properties', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(resource.id).toBeTruthy(); - expect(typeof resource.id).toBe('string'); - expect(resource.id.length).toBeGreaterThan(0); - - expect(resource.name).toBeTruthy(); - expect(typeof resource.name).toBe('string'); - expect(resource.name.length).toBeGreaterThan(0); - - expect(resource.provider).toBeTruthy(); - expect(typeof resource.provider).toBe('string'); - expect(resource.provider.length).toBeGreaterThan(0); - - expect(resource.description).toBeTruthy(); - expect(typeof resource.description).toBe('string'); - expect(resource.description.length).toBeGreaterThan(0); - }); - }); - - it('should return resources with valid category types', () => { - const resources = listToolResources(); - const validCategories = ['cloudflare', 'content', 'communications', 'database']; - - resources.forEach(resource => { - expect(validCategories).toContain(resource.category); - }); - }); - - it('should return resources with non-empty capabilities arrays', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(Array.isArray(resource.capabilities)).toBe(true); - expect(resource.capabilities.length).toBeGreaterThan(0); - resource.capabilities.forEach(capability => { - expect(typeof capability).toBe('string'); - expect(capability.length).toBeGreaterThan(0); - }); - }); - }); - - it('should have unique resource IDs', () => { - const resources = listToolResources(); - const ids = resources.map(r => r.id); - const uniqueIds = new Set(ids); - expect(uniqueIds.size).toBe(resources.length); - }); - - it('should return the same array on multiple calls', () => { - const resources1 = listToolResources(); - const resources2 = listToolResources(); - expect(resources1).toEqual(resources2); - }); - }); - - describe('Tool Resource Categories', () => { - it('should have exactly one cloudflare resource', () => { - const resources = listToolResources(); - const cloudflareResources = resources.filter(r => r.category === 'cloudflare'); - expect(cloudflareResources).toHaveLength(1); - }); - - it('should have content category resources', () => { - const resources = listToolResources(); - const contentResources = resources.filter(r => r.category === 'content'); - expect(contentResources.length).toBeGreaterThan(0); - }); - - it('should have communications category resources', () => { - const resources = listToolResources(); - const commResources = resources.filter(r => r.category === 'communications'); - expect(commResources.length).toBeGreaterThan(0); - }); - - it('should have database category resources', () => { - const resources = listToolResources(); - const dbResources = resources.filter(r => r.category === 'database'); - expect(dbResources.length).toBeGreaterThan(0); - }); - - it('should cover all expected categories', () => { - const resources = listToolResources(); - const categories = new Set(resources.map(r => r.category)); - expect(categories.has('cloudflare')).toBe(true); - expect(categories.has('content')).toBe(true); - expect(categories.has('communications')).toBe(true); - expect(categories.has('database')).toBe(true); - }); - }); - - describe('Specific Tool Resources', () => { - it('should have Cloudflare Workers resource with correct properties', () => { - const resources = listToolResources(); - const cfResource = resources.find(r => r.id === 'cloudflare.workers.assets'); - - expect(cfResource).toBeDefined(); - expect(cfResource?.name).toBe('Cloudflare Workers Evidence Tools'); - expect(cfResource?.provider).toBe('Cloudflare'); - expect(cfResource?.category).toBe('cloudflare'); - expect(cfResource?.callable).toBe(true); - expect(cfResource?.capabilities).toContain('freeze'); - expect(cfResource?.capabilities).toContain('mint'); - expect(cfResource?.capabilities).toContain('status'); - }); - - it('should have Notion Search resource with correct properties', () => { - const resources = listToolResources(); - const notionResource = resources.find(r => r.id === 'notion.search'); - - expect(notionResource).toBeDefined(); - expect(notionResource?.name).toBe('Notion Workspace Search'); - expect(notionResource?.provider).toBe('Notion'); - expect(notionResource?.category).toBe('content'); - expect(notionResource?.callable).toBe(true); - expect(notionResource?.capabilities).toContain('search'); - expect(notionResource?.capabilities).toContain('filter'); - expect(notionResource?.capabilities).toContain('page-context'); - }); - - it('should have Google Drive resource with correct properties', () => { - const resources = listToolResources(); - const driveResource = resources.find(r => r.id === 'google.drive.search'); - - expect(driveResource).toBeDefined(); - expect(driveResource?.name).toBe('Google Drive Discovery'); - expect(driveResource?.provider).toBe('Google Drive'); - expect(driveResource?.category).toBe('content'); - expect(driveResource?.callable).toBe(true); - expect(driveResource?.capabilities).toContain('search'); - expect(driveResource?.capabilities).toContain('metadata'); - expect(driveResource?.capabilities).toContain('shared-drives'); - }); - - it('should have Outlook resource with correct properties', () => { - const resources = listToolResources(); - const outlookResource = resources.find(r => r.id === 'outlook.mail.search'); - - expect(outlookResource).toBeDefined(); - expect(outlookResource?.name).toBe('Outlook / SharePoint Email + Files'); - expect(outlookResource?.provider).toBe('Microsoft 365'); - expect(outlookResource?.category).toBe('communications'); - expect(outlookResource?.callable).toBe(true); - expect(outlookResource?.capabilities).toContain('search'); - expect(outlookResource?.capabilities).toContain('attachments'); - expect(outlookResource?.capabilities).toContain('sharepoint-sites'); - }); - - it('should have Neon DB resource with correct properties', () => { - const resources = listToolResources(); - const neonResource = resources.find(r => r.id === 'neon.metadata.search'); - - expect(neonResource).toBeDefined(); - expect(neonResource?.name).toBe('Neon DB Metadata'); - expect(neonResource?.provider).toBe('Neon'); - expect(neonResource?.category).toBe('database'); - expect(neonResource?.callable).toBe(true); - expect(neonResource?.capabilities).toContain('tables'); - expect(neonResource?.capabilities).toContain('columns'); - expect(neonResource?.capabilities).toContain('lineage'); - }); - }); - - describe('API endpoint simulation - /api/tools/resources', () => { - it('should simulate API response structure for tools endpoint', () => { - const resources = listToolResources(); - const apiResponse = { - resources, - callableResources: resources.filter(r => r.callable).map(r => r.id), - }; - - expect(apiResponse).toHaveProperty('resources'); - expect(apiResponse).toHaveProperty('callableResources'); - expect(Array.isArray(apiResponse.resources)).toBe(true); - expect(Array.isArray(apiResponse.callableResources)).toBe(true); - expect(apiResponse.callableResources.length).toBe(5); - }); - - it('should verify API response has all expected callable resource IDs', () => { - const resources = listToolResources(); - const callableIds = resources.filter(r => r.callable).map(r => r.id); - - expect(callableIds).toEqual([ - 'cloudflare.workers.assets', - 'notion.search', - 'google.drive.search', - 'outlook.mail.search', - 'neon.metadata.search', - ]); - }); - - it('should simulate successful API call with mock fetch', async () => { - const resources = listToolResources(); - const mockResponse = { - resources, - callableResources: resources.filter(r => r.callable).map(r => r.id), - }; - - global.fetch = vi.fn().mockResolvedValue({ - ok: true, - status: 200, - json: () => Promise.resolve(mockResponse), - }); - - const response = await fetch('/api/tools/resources'); - const data = await response.json(); - - expect(response.ok).toBe(true); - expect(data.resources).toHaveLength(5); - expect(data.callableResources).toHaveLength(5); - }); - - it('should handle API error scenarios gracefully', async () => { - global.fetch = vi.fn().mockResolvedValue({ - ok: false, - status: 500, - json: () => Promise.resolve({ message: 'Internal server error' }), - }); - - const response = await fetch('/api/tools/resources'); - expect(response.ok).toBe(false); - expect(response.status).toBe(500); - }); - }); - - describe('Resource Provider Distribution', () => { - it('should have diverse providers', () => { - const resources = listToolResources(); - const providers = new Set(resources.map(r => r.provider)); - - expect(providers.size).toBeGreaterThan(1); - expect(providers.has('Cloudflare')).toBe(true); - expect(providers.has('Notion')).toBe(true); - expect(providers.has('Google Drive')).toBe(true); - expect(providers.has('Microsoft 365')).toBe(true); - expect(providers.has('Neon')).toBe(true); - }); - - it('should have exactly 5 unique providers', () => { - const resources = listToolResources(); - const providers = new Set(resources.map(r => r.provider)); - expect(providers.size).toBe(5); - }); - }); - - describe('Resource Capability Validation', () => { - it('should verify all resources have search-related capabilities where applicable', () => { - const resources = listToolResources(); - const searchableResources = resources.filter(r => - r.category === 'content' || - r.category === 'communications' || - r.category === 'database' - ); - - searchableResources.forEach(resource => { - expect(resource.capabilities).toContain('search'); - }); - }); - - it('should verify Cloudflare resource has blockchain-related capabilities', () => { - const resources = listToolResources(); - const cfResource = resources.find(r => r.category === 'cloudflare'); - - expect(cfResource?.capabilities).toContain('freeze'); - expect(cfResource?.capabilities).toContain('mint'); - }); - - it('should ensure all capabilities are lowercase strings', () => { - const resources = listToolResources(); - resources.forEach(resource => { - resource.capabilities.forEach(capability => { - expect(capability).toBe(capability.toLowerCase()); - expect(capability).not.toContain(' '); - }); - }); - }); - }); - - describe('Data Integrity and Immutability', () => { - it('should not allow modification of returned resource array', () => { - const resources = listToolResources(); - const originalLength = resources.length; - - // Attempt to modify - this should not affect subsequent calls - resources.push({ - id: 'test.invalid', - name: 'Test Invalid', - provider: 'Test', - description: 'Invalid', - category: 'content', - callable: false, - capabilities: ['test'], - }); - - const resources2 = listToolResources(); - expect(resources2.length).toBe(originalLength); - }); - - it('should return consistent data structure across multiple calls', () => { - const call1 = listToolResources(); - const call2 = listToolResources(); - const call3 = listToolResources(); - - expect(call1).toEqual(call2); - expect(call2).toEqual(call3); - expect(JSON.stringify(call1)).toBe(JSON.stringify(call2)); - }); - }); - - describe('Resource ID Format Validation', () => { - it('should have resource IDs in correct namespace format', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(resource.id).toMatch(/^[a-z]+\.[a-z]+\.[a-z]+$/); - }); - }); - - it('should have resource IDs with exactly 2 dots (namespace.service.action)', () => { - const resources = listToolResources(); - resources.forEach(resource => { - const dotCount = (resource.id.match(/\./g) || []).length; - expect(dotCount).toBe(2); - }); - }); - - it('should have no duplicate resource IDs', () => { - const resources = listToolResources(); - const ids = resources.map(r => r.id); - const uniqueIds = [...new Set(ids)]; - - expect(ids.length).toBe(uniqueIds.length); - }); - }); - - describe('Error Resilience', () => { - it('should handle JSON serialization correctly', () => { - const resources = listToolResources(); - const serialized = JSON.stringify(resources); - const deserialized = JSON.parse(serialized); - - expect(deserialized).toEqual(resources); - expect(Array.isArray(deserialized)).toBe(true); - expect(deserialized.length).toBe(5); - }); - - it('should handle filtering operations without errors', () => { - const resources = listToolResources(); - - expect(() => { - resources.filter(r => r.callable); - }).not.toThrow(); - - expect(() => { - resources.filter(r => r.category === 'content'); - }).not.toThrow(); - - expect(() => { - resources.map(r => r.id); - }).not.toThrow(); - }); - - it('should handle edge case searches gracefully', () => { - const resources = listToolResources(); - - const nonExistent = resources.find(r => r.id === 'non.existent.resource'); - expect(nonExistent).toBeUndefined(); - - const emptyFilter = resources.filter(r => r.category === 'nonexistent'); - expect(emptyFilter).toHaveLength(0); - }); - }); - - describe('Performance and Efficiency', () => { - it('should return results quickly', () => { - const start = performance.now(); - listToolResources(); - const end = performance.now(); - - expect(end - start).toBeLessThan(10); // Should be very fast (< 10ms) - }); - - it('should handle multiple rapid calls efficiently', () => { - const start = performance.now(); - for (let i = 0; i < 100; i++) { - listToolResources(); - } - const end = performance.now(); - - expect(end - start).toBeLessThan(100); // 100 calls in < 100ms - }); - }); - - describe('Integration with API Response Format', () => { - it('should match the expected API response structure from routes.ts', () => { - const resources = listToolResources(); - const apiResponse = { - resources, - callableResources: resources.filter(r => r.callable).map(r => r.id), - }; - - // Verify this matches the structure in routes.ts line 119-122 - expect(apiResponse).toMatchObject({ - resources: expect.any(Array), - callableResources: expect.any(Array), - }); - - expect(apiResponse.callableResources).toEqual([ - 'cloudflare.workers.assets', - 'notion.search', - 'google.drive.search', - 'outlook.mail.search', - 'neon.metadata.search', - ]); - }); - - it('should provide resources suitable for agent layer consumption', () => { - const resources = listToolResources(); - - resources.forEach(resource => { - // Each resource should provide enough information for an agent to use it - expect(resource.description.length).toBeGreaterThan(20); - expect(resource.capabilities.length).toBeGreaterThan(0); - expect(resource.callable).toBe(true); - }); - }); - }); - - describe('Documentation and Metadata Quality', () => { - it('should have meaningful descriptions for all resources', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(resource.description.length).toBeGreaterThan(30); - expect(resource.description).not.toMatch(/^test/i); - expect(resource.description).not.toMatch(/^placeholder/i); - }); - }); - - it('should have descriptive names for all resources', () => { - const resources = listToolResources(); - resources.forEach(resource => { - expect(resource.name.length).toBeGreaterThan(5); - expect(resource.name).not.toBe(resource.id); - }); - }); - - it('should have all capabilities with meaningful names', () => { - const resources = listToolResources(); - resources.forEach(resource => { - resource.capabilities.forEach(capability => { - expect(capability.length).toBeGreaterThan(2); - }); - }); - }); - }); -}); diff --git a/server/__tests__/objectStorage.test.ts b/server/__tests__/objectStorage.test.ts deleted file mode 100644 index 5a62290..0000000 --- a/server/__tests__/objectStorage.test.ts +++ /dev/null @@ -1,288 +0,0 @@ -import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { ObjectStorageService, ObjectNotFoundError } from '../objectStorage'; -import { Storage } from '@google-cloud/storage'; - -// Mock Google Cloud Storage -vi.mock('@google-cloud/storage', () => ({ - Storage: vi.fn(() => ({ - bucket: vi.fn(() => ({ - file: vi.fn(() => ({ - save: vi.fn(), - createWriteStream: vi.fn(), - download: vi.fn(), - delete: vi.fn(), - exists: vi.fn(), - getSignedUrl: vi.fn(), - makePublic: vi.fn(), - makePrivate: vi.fn(), - })), - upload: vi.fn(), - })), - })), -})); - -describe('ObjectStorageService', () => { - let storageService: ObjectStorageService; - let mockStorage: any; - let mockBucket: any; - let mockFile: any; - - beforeEach(() => { - vi.clearAllMocks(); - storageService = new ObjectStorageService(); - mockStorage = new Storage(); - mockBucket = mockStorage.bucket(); - mockFile = mockBucket.file(); - }); - - describe('uploadFile', () => { - it('should upload file successfully', async () => { - const fileBuffer = Buffer.from('test file content'); - const fileName = 'test-file.pdf'; - const contentType = 'application/pdf'; - - mockFile.save.mockResolvedValue(undefined); - mockFile.makePublic.mockResolvedValue(undefined); - mockFile.getSignedUrl.mockResolvedValue(['http://signed-url.com']); - - const result = await storageService.uploadFile(fileBuffer, fileName, contentType); - - expect(mockFile.save).toHaveBeenCalledWith(fileBuffer, { - metadata: { - contentType, - }, - public: false, - validation: 'md5', - }); - - expect(result).toEqual({ - fileName, - url: 'http://signed-url.com', - size: fileBuffer.length, - contentType, - }); - }); - - it('should handle upload errors', async () => { - const fileBuffer = Buffer.from('test content'); - const fileName = 'test-file.pdf'; - - mockFile.save.mockRejectedValue(new Error('Upload failed')); - - await expect( - storageService.uploadFile(fileBuffer, fileName, 'application/pdf') - ).rejects.toThrow('Upload failed'); - }); - }); - - describe('downloadFile', () => { - it('should download file successfully', async () => { - const fileName = 'test-file.pdf'; - const fileContent = Buffer.from('file content'); - - mockFile.exists.mockResolvedValue([true]); - mockFile.download.mockResolvedValue([fileContent]); - - const result = await storageService.downloadFile(fileName); - - expect(result).toEqual(fileContent); - expect(mockFile.download).toHaveBeenCalled(); - }); - - it('should throw ObjectNotFoundError for non-existent file', async () => { - const fileName = 'non-existent.pdf'; - - mockFile.exists.mockResolvedValue([false]); - - await expect(storageService.downloadFile(fileName)).rejects.toThrow(ObjectNotFoundError); - }); - }); - - describe('deleteFile', () => { - it('should delete file successfully', async () => { - const fileName = 'test-file.pdf'; - - mockFile.exists.mockResolvedValue([true]); - mockFile.delete.mockResolvedValue(undefined); - - await storageService.deleteFile(fileName); - - expect(mockFile.delete).toHaveBeenCalled(); - }); - - it('should throw ObjectNotFoundError when deleting non-existent file', async () => { - const fileName = 'non-existent.pdf'; - - mockFile.exists.mockResolvedValue([false]); - - await expect(storageService.deleteFile(fileName)).rejects.toThrow(ObjectNotFoundError); - }); - }); - - describe('getSignedUrl', () => { - it('should generate signed URL for file access', async () => { - const fileName = 'test-file.pdf'; - const signedUrl = 'http://signed-url.com'; - - mockFile.exists.mockResolvedValue([true]); - mockFile.getSignedUrl.mockResolvedValue([signedUrl]); - - const result = await storageService.getSignedUrl(fileName, 'read', 3600); - - expect(result).toBe(signedUrl); - expect(mockFile.getSignedUrl).toHaveBeenCalledWith({ - action: 'read', - expires: expect.any(Date), - }); - }); - - it('should generate signed URL for file upload', async () => { - const fileName = 'new-file.pdf'; - const signedUrl = 'http://upload-url.com'; - - mockFile.getSignedUrl.mockResolvedValue([signedUrl]); - - const result = await storageService.getSignedUrl(fileName, 'write', 3600); - - expect(result).toBe(signedUrl); - expect(mockFile.getSignedUrl).toHaveBeenCalledWith({ - action: 'write', - expires: expect.any(Date), - contentType: 'application/octet-stream', - }); - }); - }); - - describe('listFiles', () => { - it('should list files with prefix', async () => { - const prefix = 'assets/user-1/'; - const mockFiles = [ - { name: 'assets/user-1/file1.pdf', metadata: { size: 1024, timeCreated: '2024-01-01' } }, - { name: 'assets/user-1/file2.jpg', metadata: { size: 2048, timeCreated: '2024-01-02' } }, - ]; - - mockBucket.getFiles.mockResolvedValue([mockFiles]); - - const result = await storageService.listFiles(prefix); - - expect(result).toEqual([ - { - name: 'assets/user-1/file1.pdf', - size: 1024, - created: '2024-01-01', - }, - { - name: 'assets/user-1/file2.jpg', - size: 2048, - created: '2024-01-02', - }, - ]); - - expect(mockBucket.getFiles).toHaveBeenCalledWith({ - prefix, - autoPaginate: true, - }); - }); - - it('should handle empty file list', async () => { - const prefix = 'empty/'; - - mockBucket.getFiles.mockResolvedValue([[]]); - - const result = await storageService.listFiles(prefix); - - expect(result).toEqual([]); - }); - }); - - describe('getFileMetadata', () => { - it('should get file metadata', async () => { - const fileName = 'test-file.pdf'; - const mockMetadata = { - size: '1024', - contentType: 'application/pdf', - timeCreated: '2024-01-01T00:00:00Z', - updated: '2024-01-01T00:00:00Z', - md5Hash: 'abc123', - }; - - mockFile.exists.mockResolvedValue([true]); - mockFile.getMetadata.mockResolvedValue([mockMetadata]); - - const result = await storageService.getFileMetadata(fileName); - - expect(result).toEqual({ - size: 1024, - contentType: 'application/pdf', - created: '2024-01-01T00:00:00Z', - updated: '2024-01-01T00:00:00Z', - md5Hash: 'abc123', - }); - }); - - it('should throw ObjectNotFoundError for non-existent file metadata', async () => { - const fileName = 'non-existent.pdf'; - - mockFile.exists.mockResolvedValue([false]); - - await expect(storageService.getFileMetadata(fileName)).rejects.toThrow(ObjectNotFoundError); - }); - }); - - describe('moveFile', () => { - it('should move file to new location', async () => { - const oldFileName = 'old-location/file.pdf'; - const newFileName = 'new-location/file.pdf'; - - const mockOldFile = { ...mockFile }; - const mockNewFile = { ...mockFile }; - - mockBucket.file.mockImplementation((name: string) => { - if (name === oldFileName) return mockOldFile; - if (name === newFileName) return mockNewFile; - return mockFile; - }); - - mockOldFile.exists.mockResolvedValue([true]); - mockOldFile.move.mockResolvedValue([mockNewFile]); - - await storageService.moveFile(oldFileName, newFileName); - - expect(mockOldFile.move).toHaveBeenCalledWith(mockNewFile); - }); - - it('should throw ObjectNotFoundError when moving non-existent file', async () => { - const oldFileName = 'non-existent.pdf'; - const newFileName = 'new-location/file.pdf'; - - mockFile.exists.mockResolvedValue([false]); - - await expect(storageService.moveFile(oldFileName, newFileName)).rejects.toThrow( - ObjectNotFoundError - ); - }); - }); - - describe('copyFile', () => { - it('should copy file to new location', async () => { - const sourceFileName = 'source/file.pdf'; - const destFileName = 'dest/file.pdf'; - - const mockSourceFile = { ...mockFile }; - const mockDestFile = { ...mockFile }; - - mockBucket.file.mockImplementation((name: string) => { - if (name === sourceFileName) return mockSourceFile; - if (name === destFileName) return mockDestFile; - return mockFile; - }); - - mockSourceFile.exists.mockResolvedValue([true]); - mockSourceFile.copy.mockResolvedValue([mockDestFile]); - - await storageService.copyFile(sourceFileName, destFileName); - - expect(mockSourceFile.copy).toHaveBeenCalledWith(mockDestFile); - }); - }); -}); \ No newline at end of file diff --git a/server/__tests__/simple.test.ts b/server/__tests__/simple.test.ts deleted file mode 100644 index b14f090..0000000 --- a/server/__tests__/simple.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { describe, it, expect } from 'vitest'; - -describe('Simple QA Test', () => { - it('should verify basic math works', () => { - expect(2 + 2).toBe(4); - }); - - it('should verify string operations work', () => { - const greeting = 'Hello'; - const name = 'World'; - expect(`${greeting} ${name}`).toBe('Hello World'); - }); - - it('should verify array operations work', () => { - const numbers = [1, 2, 3]; - expect(numbers.length).toBe(3); - expect(numbers.includes(2)).toBe(true); - }); - - it('should verify object operations work', () => { - const user = { name: 'John', age: 30 }; - expect(user.name).toBe('John'); - expect(user.age).toBe(30); - }); - - it('should verify async operations work', async () => { - const promise = Promise.resolve('success'); - const result = await promise; - expect(result).toBe('success'); - }); -}); \ No newline at end of file diff --git a/server/__tests__/storage.test.ts b/server/__tests__/storage.test.ts deleted file mode 100644 index 235d1c2..0000000 --- a/server/__tests__/storage.test.ts +++ /dev/null @@ -1,311 +0,0 @@ -import { describe, it, expect, beforeEach, vi, Mock } from 'vitest'; -import { storage, Storage } from '../storage'; -import { db } from '../db'; -import { users, assets, evidence } from '@shared/schema'; -import { eq } from 'drizzle-orm'; - -// Mock the database -vi.mock('../db', () => ({ - db: { - select: vi.fn(), - insert: vi.fn(), - update: vi.fn(), - delete: vi.fn(), - }, -})); - -const mockDb = db as any; - -describe('Storage Service', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - describe('User Operations', () => { - it('should get user by id', async () => { - const mockUser = { - id: 'user-1', - email: 'test@example.com', - name: 'Test User', - createdAt: new Date(), - updatedAt: new Date(), - }; - - mockDb.select.mockReturnValue({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - limit: vi.fn().mockResolvedValue([mockUser]), - }), - }), - }); - - const result = await storage.getUser('user-1'); - expect(result).toEqual(mockUser); - }); - - it('should return undefined for non-existent user', async () => { - mockDb.select.mockReturnValue({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - limit: vi.fn().mockResolvedValue([]), - }), - }), - }); - - const result = await storage.getUser('non-existent'); - expect(result).toBeUndefined(); - }); - - it('should upsert user', async () => { - const userToUpsert = { - id: 'user-1', - email: 'test@example.com', - name: 'Test User', - }; - - const mockUser = { - ...userToUpsert, - createdAt: new Date(), - updatedAt: new Date(), - }; - - mockDb.insert.mockReturnValue({ - values: vi.fn().mockReturnValue({ - onConflictDoUpdate: vi.fn().mockReturnValue({ - returning: vi.fn().mockResolvedValue([mockUser]), - }), - }), - }); - - const result = await storage.upsertUser(userToUpsert); - expect(result).toEqual(mockUser); - }); - }); - - describe('Asset Operations', () => { - it('should create asset', async () => { - const assetData = { - title: 'Test Asset', - description: 'Test Description', - userId: 'user-1', - value: 1000, - currency: 'USD', - category: 'electronics', - status: 'active' as const, - }; - - const mockAsset = { - id: 'asset-1', - ...assetData, - createdAt: new Date(), - updatedAt: new Date(), - }; - - mockDb.insert.mockReturnValue({ - values: vi.fn().mockReturnValue({ - returning: vi.fn().mockResolvedValue([mockAsset]), - }), - }); - - const result = await storage.createAsset(assetData); - expect(result).toEqual(mockAsset); - }); - - it('should get asset by id and userId', async () => { - const mockAsset = { - id: 'asset-1', - title: 'Test Asset', - userId: 'user-1', - createdAt: new Date(), - updatedAt: new Date(), - }; - - mockDb.select.mockReturnValue({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - limit: vi.fn().mockResolvedValue([mockAsset]), - }), - }), - }); - - const result = await storage.getAsset('asset-1', 'user-1'); - expect(result).toEqual(mockAsset); - }); - - it('should get user assets with filters', async () => { - const mockAssets = [ - { - id: 'asset-1', - title: 'Test Asset 1', - category: 'electronics', - status: 'active', - userId: 'user-1', - }, - { - id: 'asset-2', - title: 'Test Asset 2', - category: 'furniture', - status: 'active', - userId: 'user-1', - }, - ]; - - mockDb.select.mockReturnValue({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - orderBy: vi.fn().mockResolvedValue(mockAssets), - }), - }), - }); - - const result = await storage.getUserAssets('user-1', { - category: 'electronics', - status: 'active', - }); - - expect(result).toEqual(mockAssets); - }); - - it('should update asset', async () => { - const updates = { title: 'Updated Asset' }; - const mockUpdatedAsset = { - id: 'asset-1', - title: 'Updated Asset', - userId: 'user-1', - updatedAt: new Date(), - }; - - mockDb.update.mockReturnValue({ - set: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - returning: vi.fn().mockResolvedValue([mockUpdatedAsset]), - }), - }), - }); - - const result = await storage.updateAsset('asset-1', 'user-1', updates); - expect(result).toEqual(mockUpdatedAsset); - }); - - it('should delete asset', async () => { - mockDb.delete.mockReturnValue({ - where: vi.fn().mockResolvedValue(undefined), - }); - - await expect(storage.deleteAsset('asset-1', 'user-1')).resolves.not.toThrow(); - }); - }); - - describe('Evidence Operations', () => { - it('should create evidence', async () => { - const evidenceData = { - assetId: 'asset-1', - userId: 'user-1', - type: 'receipt' as const, - title: 'Purchase Receipt', - description: 'Original purchase receipt', - filePath: '/uploads/receipt.pdf', - fileSize: 1024, - mimeType: 'application/pdf', - }; - - const mockEvidence = { - id: 'evidence-1', - ...evidenceData, - createdAt: new Date(), - updatedAt: new Date(), - }; - - mockDb.insert.mockReturnValue({ - values: vi.fn().mockReturnValue({ - returning: vi.fn().mockResolvedValue([mockEvidence]), - }), - }); - - const result = await storage.createEvidence(evidenceData); - expect(result).toEqual(mockEvidence); - }); - - it('should get asset evidence', async () => { - const mockEvidence = [ - { - id: 'evidence-1', - assetId: 'asset-1', - type: 'receipt', - title: 'Purchase Receipt', - }, - { - id: 'evidence-2', - assetId: 'asset-1', - type: 'photo', - title: 'Product Photo', - }, - ]; - - mockDb.select.mockReturnValue({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - orderBy: vi.fn().mockResolvedValue(mockEvidence), - }), - }), - }); - - const result = await storage.getAssetEvidence('asset-1', 'user-1'); - expect(result).toEqual(mockEvidence); - }); - }); - - describe('Asset Statistics', () => { - it('should get asset stats', async () => { - const mockStats = { - totalAssets: 10, - totalValue: 25000, - assetsByCategory: { - electronics: 5, - furniture: 3, - vehicles: 2, - }, - assetsByStatus: { - active: 8, - frozen: 1, - immutable: 1, - }, - }; - - // Mock the SQL queries for statistics - mockDb.select.mockReturnValueOnce({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockResolvedValue([{ count: 10, totalValue: 25000 }]), - }), - }); - - mockDb.select.mockReturnValueOnce({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - groupBy: vi.fn().mockResolvedValue([ - { category: 'electronics', count: 5 }, - { category: 'furniture', count: 3 }, - { category: 'vehicles', count: 2 }, - ]), - }), - }), - }); - - mockDb.select.mockReturnValueOnce({ - from: vi.fn().mockReturnValue({ - where: vi.fn().mockReturnValue({ - groupBy: vi.fn().mockResolvedValue([ - { status: 'active', count: 8 }, - { status: 'frozen', count: 1 }, - { status: 'immutable', count: 1 }, - ]), - }), - }), - }); - - const result = await storage.getAssetStats('user-1'); - expect(result.totalAssets).toBe(10); - expect(result.totalValue).toBe(25000); - }); - }); -}); \ No newline at end of file diff --git a/server/aiAnalysis.ts b/server/aiAnalysis.ts deleted file mode 100644 index d75c1fa..0000000 --- a/server/aiAnalysis.ts +++ /dev/null @@ -1,227 +0,0 @@ -import OpenAI from "openai"; - -// the newest OpenAI model is "gpt-4o" which was released May 13, 2024. do not change this unless explicitly requested by the user -const openai = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY_ENV_VAR || "default_key" -}); - -export interface ReceiptAnalysis { - merchant: string; - amount: number; - currency: string; - date: string; - items: Array<{ - description: string; - quantity: number; - price: number; - }>; - taxAmount?: number; - confidence: number; - category: string; -} - -export interface DocumentAnalysis { - documentType: string; - keyFields: Record; - confidence: number; - summary: string; - extractedText: string; -} - -export interface AssetValuation { - estimatedValue: number; - currency: string; - confidence: number; - factors: string[]; - marketComparisons?: Array<{ - source: string; - price: number; - similarity: number; - }>; -} - -export class AIAnalysisService { - async analyzeReceipt(base64Image: string): Promise { - try { - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are an expert receipt analyzer. Analyze the receipt image and extract structured data. - Respond with JSON in this exact format: { - "merchant": string, - "amount": number, - "currency": string, - "date": string (ISO format), - "items": [{"description": string, "quantity": number, "price": number}], - "taxAmount": number, - "confidence": number (0-1), - "category": string - }` - }, - { - role: "user", - content: [ - { - type: "text", - text: "Analyze this receipt and extract all the key information including merchant, total amount, date, individual items, and tax amount." - }, - { - type: "image_url", - image_url: { - url: `data:image/jpeg;base64,${base64Image}` - } - } - ], - }, - ], - response_format: { type: "json_object" }, - max_tokens: 1000, - }); - - const result = JSON.parse(response.choices[0].message.content || '{}'); - return result as ReceiptAnalysis; - } catch (error) { - throw new Error("Failed to analyze receipt: " + (error as Error).message); - } - } - - async analyzeDocument(base64Image: string): Promise { - try { - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are an expert document analyzer. Analyze the document image and extract structured data. - Respond with JSON in this exact format: { - "documentType": string, - "keyFields": object, - "confidence": number (0-1), - "summary": string, - "extractedText": string - }` - }, - { - role: "user", - content: [ - { - type: "text", - text: "Analyze this document and extract the document type, key fields, and provide a summary of the content." - }, - { - type: "image_url", - image_url: { - url: `data:image/jpeg;base64,${base64Image}` - } - } - ], - }, - ], - response_format: { type: "json_object" }, - max_tokens: 1500, - }); - - const result = JSON.parse(response.choices[0].message.content || '{}'); - return result as DocumentAnalysis; - } catch (error) { - throw new Error("Failed to analyze document: " + (error as Error).message); - } - } - - async analyzeAssetPhoto(base64Image: string, assetType: string): Promise { - try { - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are an expert asset appraiser. Analyze the asset photo and provide valuation insights. - Respond with JSON in this exact format: { - "estimatedValue": number, - "currency": string, - "confidence": number (0-1), - "factors": [string], - "marketComparisons": [{"source": string, "price": number, "similarity": number}] - }` - }, - { - role: "user", - content: [ - { - type: "text", - text: `Analyze this ${assetType} photo and provide an estimated value based on visible condition, brand, model, and other factors. Include factors that influenced your valuation.` - }, - { - type: "image_url", - image_url: { - url: `data:image/jpeg;base64,${base64Image}` - } - } - ], - }, - ], - response_format: { type: "json_object" }, - max_tokens: 1000, - }); - - const result = JSON.parse(response.choices[0].message.content || '{}'); - return result as AssetValuation; - } catch (error) { - throw new Error("Failed to analyze asset: " + (error as Error).message); - } - } - - async generateLegalDocument(templateType: string, assetData: any, jurisdiction: string): Promise { - try { - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are an expert legal document generator. Generate a professional ${templateType} document for ${jurisdiction} jurisdiction. Use proper legal formatting and language.` - }, - { - role: "user", - content: `Generate a ${templateType} document with the following asset information: ${JSON.stringify(assetData)}. Include all necessary legal clauses and make it court-ready.` - }, - ], - max_tokens: 2000, - }); - - return response.choices[0].message.content || ''; - } catch (error) { - throw new Error("Failed to generate legal document: " + (error as Error).message); - } - } - - async calculateTrustScore(asset: any, evidence: any[]): Promise { - try { - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are a trust scoring expert. Analyze the asset and evidence data to calculate a trust score from 0.0 to 100.0. - Respond with JSON: {"trustScore": number, "factors": [string]}` - }, - { - role: "user", - content: `Calculate trust score for this asset: ${JSON.stringify(asset)} with evidence: ${JSON.stringify(evidence)}. Consider verification status, documentation completeness, blockchain verification, and source credibility.` - }, - ], - response_format: { type: "json_object" }, - max_tokens: 500, - }); - - const result = JSON.parse(response.choices[0].message.content || '{"trustScore": 0}'); - return Math.max(0, Math.min(100, result.trustScore)); - } catch (error) { - console.error("Failed to calculate trust score:", error); - return 0; - } - } -} - -export const aiAnalysisService = new AIAnalysisService(); diff --git a/server/chittyAuth.ts b/server/chittyAuth.ts deleted file mode 100644 index 399898b..0000000 --- a/server/chittyAuth.ts +++ /dev/null @@ -1,402 +0,0 @@ -/** - * ChittyAuth - Unified authentication system for ChittyOS ecosystem - * Combines ChittyID (identity management) + ChittyVerify (verification layer) - * Underpinned by Clerk for secure authentication infrastructure - */ - -import { clerkMiddleware, requireAuth, getAuth, createClerkClient } from '@clerk/express'; -import type { Express, RequestHandler, Request, Response, NextFunction } from 'express'; -import { storage } from './storage'; - -// Initialize Clerk client with environment variables -const clerk = createClerkClient({ - secretKey: process.env.CLERK_SECRET_KEY || '', - publishableKey: process.env.CLERK_PUBLISHABLE_KEY || '', -}); - -/** - * ChittyID - Identity management service - * Handles user identification and profile management - */ -export class ChittyID { - private static instance: ChittyID; - - private constructor() {} - - static getInstance(): ChittyID { - if (!ChittyID.instance) { - ChittyID.instance = new ChittyID(); - } - return ChittyID.instance; - } - - async createIdentity(clerkUserId: string, metadata: any) { - // Create ChittyID from Clerk user - const clerkUser = await clerk.users.getUser(clerkUserId); - - const chittyId = { - id: `chitty_${clerkUserId}`, - clerkId: clerkUserId, - email: clerkUser.emailAddresses[0]?.emailAddress, - firstName: clerkUser.firstName, - lastName: clerkUser.lastName, - profileImageUrl: clerkUser.imageUrl, - verificationStatus: 'pending', - createdAt: new Date(), - metadata: { - ...metadata, - primaryEmail: clerkUser.emailAddresses[0]?.emailAddress, - phoneNumber: clerkUser.phoneNumbers[0]?.phoneNumber, - } - }; - - // Store in database - await storage.upsertUser({ - id: chittyId.id, - email: chittyId.email, - firstName: chittyId.firstName, - lastName: chittyId.lastName, - profileImageUrl: chittyId.profileImageUrl, - }); - - return chittyId; - } - - async getIdentity(chittyId: string) { - return await storage.getUser(chittyId); - } - - async updateIdentity(chittyId: string, updates: any) { - // Update both Clerk and local database - const user = await storage.getUser(chittyId); - if (!user) throw new Error('ChittyID not found'); - - // Extract Clerk ID from ChittyID - const clerkId = chittyId.replace('chitty_', ''); - - // Update Clerk user - await clerk.users.updateUser(clerkId, { - firstName: updates.firstName, - lastName: updates.lastName, - }); - - // Update local database - await storage.upsertUser({ - id: chittyId, - email: updates.email || user.email, - firstName: updates.firstName || user.firstName, - lastName: updates.lastName || user.lastName, - profileImageUrl: updates.profileImageUrl || user.profileImageUrl, - }); - - return await this.getIdentity(chittyId); - } -} - -/** - * ChittyVerify - Verification and validation layer - * Handles multi-factor authentication and identity verification - */ -export class ChittyVerify { - private static instance: ChittyVerify; - - private constructor() {} - - static getInstance(): ChittyVerify { - if (!ChittyVerify.instance) { - ChittyVerify.instance = new ChittyVerify(); - } - return ChittyVerify.instance; - } - - async verifyIdentity(chittyId: string, verificationMethod: 'email' | 'phone' | 'document'): Promise { - // Extract Clerk ID - const clerkId = chittyId.replace('chitty_', ''); - const clerkUser = await clerk.users.getUser(clerkId); - - switch (verificationMethod) { - case 'email': - // Check if primary email is verified in Clerk - const primaryEmail = clerkUser.emailAddresses.find(e => e.id === clerkUser.primaryEmailAddressId); - return primaryEmail?.verification?.status === 'verified'; - - case 'phone': - // Check if primary phone is verified in Clerk - const primaryPhone = clerkUser.phoneNumbers.find(p => p.id === clerkUser.primaryPhoneNumberId); - return primaryPhone?.verification?.status === 'verified'; - - case 'document': - // Custom document verification logic - // This could integrate with a document verification service - return await this.verifyDocument(chittyId); - - default: - return false; - } - } - - async verifyDocument(chittyId: string): Promise { - // Placeholder for document verification - // In production, this would integrate with document verification services - // For now, we'll check if user has uploaded verification documents - const user = await storage.getUser(chittyId); - return user?.verificationStatus === 'verified'; - } - - async initiateVerification(chittyId: string, method: 'email' | 'phone') { - const clerkId = chittyId.replace('chitty_', ''); - - if (method === 'email') { - // Trigger email verification through Clerk - await clerk.users.updateUser(clerkId, { - publicMetadata: { - verificationRequested: true, - verificationMethod: method, - requestedAt: new Date().toISOString(), - } - }); - } else if (method === 'phone') { - // Trigger phone verification through Clerk - await clerk.users.updateUser(clerkId, { - publicMetadata: { - verificationRequested: true, - verificationMethod: method, - requestedAt: new Date().toISOString(), - } - }); - } - - return { success: true, method }; - } - - async getVerificationStatus(chittyId: string) { - const emailVerified = await this.verifyIdentity(chittyId, 'email'); - const phoneVerified = await this.verifyIdentity(chittyId, 'phone'); - const documentVerified = await this.verifyDocument(chittyId); - - return { - chittyId, - email: emailVerified, - phone: phoneVerified, - document: documentVerified, - overallStatus: emailVerified && (phoneVerified || documentVerified) ? 'verified' : 'pending', - verificationLevel: this.calculateVerificationLevel(emailVerified, phoneVerified, documentVerified), - }; - } - - private calculateVerificationLevel(email: boolean, phone: boolean, document: boolean): number { - let level = 0; - if (email) level += 1; - if (phone) level += 1; - if (document) level += 2; // Document verification has higher weight - return level; - } -} - -/** - * ChittyAuth - Main authentication service - * Orchestrates ChittyID and ChittyVerify with Clerk - */ -export class ChittyAuth { - private chittyId: ChittyID; - private chittyVerify: ChittyVerify; - - constructor() { - this.chittyId = ChittyID.getInstance(); - this.chittyVerify = ChittyVerify.getInstance(); - } - - /** - * Setup ChittyAuth with Express app - */ - async setupAuth(app: Express) { - // Health check endpoint - app.get('/api/auth/health', (req, res) => { - res.json({ - status: 'healthy', - service: 'ChittyAuth', - components: { - chittyId: 'active', - chittyVerify: 'active', - clerk: 'active', - } - }); - }); - - // Sign up with ChittyAuth - app.post('/api/auth/signup', async (req, res) => { - try { - const { email, password, firstName, lastName, phoneNumber } = req.body; - - // Create user in Clerk - const clerkUser = await clerk.users.createUser({ - emailAddress: [email], - password, - firstName, - lastName, - phoneNumber: phoneNumber ? [phoneNumber] : undefined, - }); - - // Create ChittyID - const chittyIdentity = await this.chittyId.createIdentity(clerkUser.id, { - signupSource: 'chittyassets', - signupDate: new Date().toISOString(), - }); - - // Initiate email verification - await this.chittyVerify.initiateVerification(chittyIdentity.id, 'email'); - - res.json({ - success: true, - chittyId: chittyIdentity.id, - message: 'ChittyID created successfully. Please verify your email.', - }); - } catch (error) { - console.error('ChittyAuth signup error:', error); - res.status(400).json({ - success: false, - message: 'Failed to create ChittyID', - error: error instanceof Error ? error.message : 'Unknown error', - }); - } - }); - - // Verify identity - app.post('/api/auth/verify', requireAuth(), async (req: Request, res) => { - try { - const auth = getAuth(req); - const clerkId = auth.userId; - const chittyId = `chitty_${clerkId}`; - const { method } = req.body; - - const result = await this.chittyVerify.initiateVerification(chittyId, method); - - res.json({ - success: true, - ...result, - }); - } catch (error) { - res.status(400).json({ - success: false, - message: 'Verification failed', - }); - } - }); - - // Get verification status - app.get('/api/auth/verification-status', requireAuth(), async (req: Request, res) => { - try { - const auth = getAuth(req); - const clerkId = auth.userId; - const chittyId = `chitty_${clerkId}`; - - const status = await this.chittyVerify.getVerificationStatus(chittyId); - - res.json(status); - } catch (error) { - res.status(400).json({ - success: false, - message: 'Failed to get verification status', - }); - } - }); - - // Get ChittyID profile - app.get('/api/auth/profile', requireAuth(), async (req: Request, res) => { - try { - const auth = getAuth(req); - const clerkId = auth.userId; - const chittyId = `chitty_${clerkId}`; - - const identity = await this.chittyId.getIdentity(chittyId); - const verificationStatus = await this.chittyVerify.getVerificationStatus(chittyId); - - res.json({ - ...identity, - verification: verificationStatus, - }); - } catch (error) { - res.status(400).json({ - success: false, - message: 'Failed to get profile', - }); - } - }); - - // Update ChittyID profile - app.put('/api/auth/profile', requireAuth(), async (req: Request, res) => { - try { - const auth = getAuth(req); - const clerkId = auth.userId; - const chittyId = `chitty_${clerkId}`; - - const updated = await this.chittyId.updateIdentity(chittyId, req.body); - - res.json({ - success: true, - profile: updated, - }); - } catch (error) { - res.status(400).json({ - success: false, - message: 'Failed to update profile', - }); - } - }); - } - - /** - * Middleware to require ChittyAuth authentication - */ - requireAuth(): RequestHandler { - return requireAuth(); - } - - /** - * Middleware to optionally include ChittyAuth authentication - */ - withAuth(): RequestHandler { - return clerkMiddleware(); - } - - /** - * Middleware to require verified ChittyID - */ - requireVerified(): RequestHandler { - return async (req: Request, res: Response, next: NextFunction) => { - try { - // First check Clerk auth - await requireAuth()(req, res, async () => { - const auth = getAuth(req); - const clerkId = auth.userId; - const chittyId = `chitty_${clerkId}`; - - const status = await this.chittyVerify.getVerificationStatus(chittyId); - - if (status.overallStatus === 'verified') { - next(); - } else { - res.status(403).json({ - success: false, - message: 'ChittyID verification required', - verificationStatus: status, - }); - } - }); - } catch (error) { - res.status(401).json({ - success: false, - message: 'Authentication required', - }); - } - }; - } -} - -// Export singleton instance -export const chittyAuth = new ChittyAuth(); - -// Export middleware functions for convenience -export const requireChittyAuth = () => chittyAuth.requireAuth(); -export const withChittyAuth = () => chittyAuth.withAuth(); -export const requireVerifiedChitty = () => chittyAuth.requireVerified(); \ No newline at end of file diff --git a/server/chittyCloudMcp.ts b/server/chittyCloudMcp.ts deleted file mode 100644 index f92c1c4..0000000 --- a/server/chittyCloudMcp.ts +++ /dev/null @@ -1,291 +0,0 @@ -import { z } from "zod"; - -// ChittyCloud MCP Client for integrating with ChittyChain ecosystem -export class ChittyCloudMCP { - private baseUrl: string; - private apiKey: string; - - constructor() { - this.baseUrl = process.env.CHITTY_CLOUD_BASE_URL || 'https://api.chittycloud.com'; - this.apiKey = process.env.CHITTY_CLOUD_API_KEY || ''; - } - - // ChittyChain identifier generation (UUID v7 format) - async generateChittyId(): Promise { - try { - const response = await fetch(`${this.baseUrl}/v1/identifiers/generate`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${this.apiKey}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ version: 'v7', type: 'asset' }), - }); - - if (!response.ok) { - // Fallback to local UUID v7 generation - return this.generateUUIDv7(); - } - - const data = await response.json(); - return data.chittyId; - } catch (error) { - console.warn('ChittyCloud ID generation failed, using fallback:', error); - return this.generateUUIDv7(); - } - } - - // Freeze asset on ChittyChain (7-day immutability period) - async freezeAsset(chittyId: string, assetData: any): Promise<{ - success: boolean; - ipfsHash?: string; - freezeTimestamp?: string; - error?: string; - }> { - try { - const response = await fetch(`${this.baseUrl}/v1/chain/freeze`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${this.apiKey}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - chittyId, - assetData, - freezeDuration: '7d', - metadata: { - source: 'ChittyAssets', - timestamp: new Date().toISOString(), - } - }), - }); - - if (!response.ok) { - return { success: false, error: 'ChittyChain freeze failed' }; - } - - const data = await response.json(); - return { - success: true, - ipfsHash: data.ipfsHash, - freezeTimestamp: data.freezeTimestamp, - }; - } catch (error) { - console.error('ChittyChain freeze error:', error); - return { success: false, error: 'Network error during freeze' }; - } - } - - // Mint evidence token on ChittyChain - async mintAssetToken(chittyId: string, evidenceHash: string): Promise<{ - success: boolean; - tokenId?: string; - transactionHash?: string; - error?: string; - }> { - try { - const response = await fetch(`${this.baseUrl}/v1/chain/mint`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${this.apiKey}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - chittyId, - evidenceHash, - mintingFee: '0.1', // 0.1 CHITTY tokens - }), - }); - - if (!response.ok) { - return { success: false, error: 'Token minting failed' }; - } - - const data = await response.json(); - return { - success: true, - tokenId: data.tokenId, - transactionHash: data.transactionHash, - }; - } catch (error) { - console.error('Token minting error:', error); - return { success: false, error: 'Network error during minting' }; - } - } - - // Calculate trust score using ChittyTrust service - async calculateTrustScore(chittyId: string, assetData: any): Promise<{ - trustScore: number; - confidence: number; - factors: string[]; - }> { - try { - const response = await fetch(`${this.baseUrl}/v1/trust/score`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${this.apiKey}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - chittyId, - assetData, - includeFactors: true, - }), - }); - - if (!response.ok) { - // Fallback trust score calculation - return this.calculateFallbackTrustScore(assetData); - } - - const data = await response.json(); - return { - trustScore: data.score, - confidence: data.confidence, - factors: data.factors || [], - }; - } catch (error) { - console.warn('ChittyTrust score calculation failed, using fallback:', error); - return this.calculateFallbackTrustScore(assetData); - } - } - - // Verify asset ownership through ChittyID integration - async verifyOwnership(chittyId: string, userId: string): Promise<{ - verified: boolean; - confidence: number; - verificationMethod: string; - }> { - try { - const response = await fetch(`${this.baseUrl}/v1/identity/verify-ownership`, { - method: 'POST', - headers: { - 'Authorization': `Bearer ${this.apiKey}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - chittyId, - userId, - }), - }); - - if (!response.ok) { - return { - verified: false, - confidence: 0, - verificationMethod: 'offline', - }; - } - - const data = await response.json(); - return { - verified: data.verified, - confidence: data.confidence, - verificationMethod: data.method, - }; - } catch (error) { - console.error('Ownership verification error:', error); - return { - verified: false, - confidence: 0, - verificationMethod: 'error', - }; - } - } - - // Check ecosystem service status - async getEcosystemStatus(): Promise<{ - chittyId: 'online' | 'degraded' | 'offline'; - chittyAssets: 'active' | 'maintenance' | 'offline'; - chittyTrust: 'online' | 'degraded' | 'offline'; - chittyResolution: 'available' | 'busy' | 'offline'; - chittyChain: 'synced' | 'syncing' | 'offline'; - }> { - try { - const response = await fetch(`${this.baseUrl}/v1/ecosystem/status`, { - headers: { - 'Authorization': `Bearer ${this.apiKey}`, - }, - }); - - if (!response.ok) { - return this.getFallbackEcosystemStatus(); - } - - const data = await response.json(); - return data.services; - } catch (error) { - console.warn('Ecosystem status check failed, using fallback'); - return this.getFallbackEcosystemStatus(); - } - } - - // Private helper methods - private generateUUIDv7(): string { - // UUID v7 format: time-based with random component - const timestamp = Date.now(); - const timestampHex = timestamp.toString(16).padStart(12, '0'); - const randomHex = Array.from({ length: 18 }, () => - Math.floor(Math.random() * 16).toString(16) - ).join(''); - - return [ - timestampHex.slice(0, 8), - timestampHex.slice(8, 12), - '7' + randomHex.slice(0, 3), // Version 7 - (parseInt(randomHex.slice(3, 4), 16) & 0x3 | 0x8).toString(16) + randomHex.slice(4, 7), // Variant - randomHex.slice(7, 17) - ].join('-'); - } - - private calculateFallbackTrustScore(assetData: any): { - trustScore: number; - confidence: number; - factors: string[]; - } { - let score = 50; // Base score - const factors: string[] = []; - - // Asset value verification - if (assetData.purchasePrice && assetData.currentValue) { - score += 15; - factors.push('Purchase and current value documented'); - } - - // Serial number/identifier - if (assetData.serialNumber || assetData.model) { - score += 10; - factors.push('Unique identifier present'); - } - - // Evidence and documentation - if (assetData.evidenceCount > 0) { - score += 10; - factors.push('Supporting evidence available'); - } - - // Verification status - if (assetData.verificationStatus === 'verified') { - score += 15; - factors.push('Third-party verification completed'); - } - - return { - trustScore: Math.min(100, score), - confidence: 0.8, - factors, - }; - } - - private getFallbackEcosystemStatus() { - return { - chittyId: 'online' as const, - chittyAssets: 'active' as const, - chittyTrust: 'online' as const, - chittyResolution: 'available' as const, - chittyChain: 'synced' as const, - }; - } -} - -export const chittyCloudMcp = new ChittyCloudMCP(); \ No newline at end of file diff --git a/server/chittyCloudflareCore.ts b/server/chittyCloudflareCore.ts deleted file mode 100644 index 4801188..0000000 --- a/server/chittyCloudflareCore.ts +++ /dev/null @@ -1,545 +0,0 @@ -import { z } from "zod"; - -/** - * Configuration schemas for ChittyCloudflare Core services - */ -const ServiceConfigSchema = z.object({ - enabled: z.boolean().default(false), - domain: z.string().optional(), - apiKey: z.string().optional(), - region: z.string().default('auto'), -}); - -const AIConfigSchema = z.object({ - enabled: z.boolean().default(false), - vectorize: z.object({ - enabled: z.boolean().default(false), - indexName: z.string().optional(), - }).optional(), - workers: z.object({ - enabled: z.boolean().default(false), - scriptName: z.string().optional(), - }).optional(), -}); - -const CoreConfigSchema = z.object({ - services: z.object({ - schema: ServiceConfigSchema.optional(), - id: ServiceConfigSchema.optional(), - assets: ServiceConfigSchema.optional(), - trust: ServiceConfigSchema.optional(), - resolution: ServiceConfigSchema.optional(), - file: ServiceConfigSchema.optional(), - chain: ServiceConfigSchema.optional(), - }), - ai: AIConfigSchema.optional(), - cloudflare: z.object({ - accountId: z.string().optional(), - apiToken: z.string().optional(), - zone: z.string().optional(), - }).optional(), -}); - -export type ChittyCloudflareConfig = z.infer; - -/** - * Service status types - */ -export type ServiceStatus = 'online' | 'degraded' | 'offline' | 'maintenance'; - -export interface EcosystemStatus { - schema: ServiceStatus; - id: ServiceStatus; - assets: ServiceStatus; - trust: ServiceStatus; - resolution: ServiceStatus; - file: ServiceStatus; - chain: ServiceStatus; -} - -/** - * ChittyCloudflare Core - Unified service orchestration for ChittyOS ecosystem - * Provides high-level abstractions for all ChittyChain services running on Cloudflare - */ -export class ChittyCloudflareCore { - private config: ChittyCloudflareConfig; - private initialized: boolean = false; - private services: Map = new Map(); - - constructor(config: ChittyCloudflareConfig) { - // Validate and store configuration - this.config = CoreConfigSchema.parse(config); - } - - /** - * Initialize all enabled services and establish connections - */ - async initialize(): Promise { - if (this.initialized) { - console.warn('ChittyCloudflareCore already initialized'); - return; - } - - console.log('🚀 Initializing ChittyCloudflare Core...'); - - try { - // Initialize each enabled service - await this.initializeServices(); - - // Initialize AI services if enabled - if (this.config.ai?.enabled) { - await this.initializeAI(); - } - - // Perform health checks - await this.performHealthChecks(); - - this.initialized = true; - console.log('✅ ChittyCloudflare Core initialized successfully'); - - } catch (error) { - console.error('❌ Failed to initialize ChittyCloudflare Core:', error); - throw new Error(`ChittyCloudflare Core initialization failed: ${error}`); - } - } - - /** - * Get ecosystem-wide service status - */ - async getEcosystemStatus(): Promise { - const status: EcosystemStatus = { - schema: 'offline', - id: 'offline', - assets: 'offline', - trust: 'offline', - resolution: 'offline', - file: 'offline', - chain: 'offline', - }; - - // Check each service - for (const [serviceName, serviceConfig] of Object.entries(this.config.services)) { - if (serviceConfig?.enabled) { - try { - const serviceStatus = await this.checkServiceHealth(serviceName, serviceConfig); - (status as any)[serviceName] = serviceStatus; - } catch (error) { - console.warn(`Health check failed for ${serviceName}:`, error); - (status as any)[serviceName] = 'offline'; - } - } - } - - return status; - } - - /** - * ChittySchema Service - Schema registry and validation - */ - async schema() { - return this.getServiceProxy('schema', { - // Register a new schema - register: async (schemaId: string, schema: any) => { - return this.callService('schema', '/register', { - method: 'POST', - body: { schemaId, schema }, - }); - }, - - // Validate data against schema - validate: async (schemaId: string, data: any) => { - return this.callService('schema', '/validate', { - method: 'POST', - body: { schemaId, data }, - }); - }, - - // Get schema by ID - get: async (schemaId: string) => { - return this.callService('schema', `/schemas/${schemaId}`, { - method: 'GET', - }); - }, - }); - } - - /** - * ChittyID Service - Identity management and verification - */ - async id() { - return this.getServiceProxy('id', { - // Generate new ChittyID - generate: async (type: 'user' | 'asset' | 'organization' = 'user') => { - return this.callService('id', '/generate', { - method: 'POST', - body: { type, version: 'v7' }, - }); - }, - - // Verify ChittyID ownership - verify: async (chittyId: string, proof: any) => { - return this.callService('id', '/verify', { - method: 'POST', - body: { chittyId, proof }, - }); - }, - - // Get ChittyID metadata - get: async (chittyId: string) => { - return this.callService('id', `/identities/${chittyId}`, { - method: 'GET', - }); - }, - }); - } - - /** - * ChittyAssets Service - Asset registry and management - */ - async assets() { - return this.getServiceProxy('assets', { - // Register new asset - register: async (assetData: any) => { - return this.callService('assets', '/register', { - method: 'POST', - body: assetData, - }); - }, - - // Update asset information - update: async (chittyId: string, updates: any) => { - return this.callService('assets', `/assets/${chittyId}`, { - method: 'PATCH', - body: updates, - }); - }, - - // Get asset by ChittyID - get: async (chittyId: string) => { - return this.callService('assets', `/assets/${chittyId}`, { - method: 'GET', - }); - }, - - // Freeze asset (7-day immutability period) - freeze: async (chittyId: string) => { - return this.callService('assets', `/assets/${chittyId}/freeze`, { - method: 'POST', - }); - }, - }); - } - - /** - * ChittyTrust Service - Trust scoring and verification - */ - async trust() { - return this.getServiceProxy('trust', { - // Calculate trust score - calculate: async (chittyId: string, context?: any) => { - return this.callService('trust', '/calculate', { - method: 'POST', - body: { chittyId, context }, - }); - }, - - // Get trust history - history: async (chittyId: string) => { - return this.callService('trust', `/trust/${chittyId}/history`, { - method: 'GET', - }); - }, - - // Submit trust evidence - evidence: async (chittyId: string, evidence: any) => { - return this.callService('trust', `/trust/${chittyId}/evidence`, { - method: 'POST', - body: evidence, - }); - }, - }); - } - - /** - * ChittyResolution Service - Dispute resolution and arbitration - */ - async resolution() { - return this.getServiceProxy('resolution', { - // File a dispute - dispute: async (chittyId: string, disputeData: any) => { - return this.callService('resolution', '/disputes', { - method: 'POST', - body: { chittyId, ...disputeData }, - }); - }, - - // Get dispute status - getDispute: async (disputeId: string) => { - return this.callService('resolution', `/disputes/${disputeId}`, { - method: 'GET', - }); - }, - - // Submit evidence for dispute - submitEvidence: async (disputeId: string, evidence: any) => { - return this.callService('resolution', `/disputes/${disputeId}/evidence`, { - method: 'POST', - body: evidence, - }); - }, - }); - } - - /** - * ChittyFile Service - Decentralized file storage - */ - async file() { - return this.getServiceProxy('file', { - // Upload file - upload: async (file: Buffer | Uint8Array, metadata: any) => { - return this.callService('file', '/upload', { - method: 'POST', - body: { file: Array.from(file), metadata }, - }); - }, - - // Get file - get: async (fileId: string) => { - return this.callService('file', `/files/${fileId}`, { - method: 'GET', - }); - }, - - // Pin file to IPFS - pin: async (fileId: string) => { - return this.callService('file', `/files/${fileId}/pin`, { - method: 'POST', - }); - }, - }); - } - - /** - * ChittyChain Service - Blockchain operations - */ - async chain() { - return this.getServiceProxy('chain', { - // Mint asset token - mint: async (chittyId: string, metadata: any) => { - return this.callService('chain', '/mint', { - method: 'POST', - body: { chittyId, metadata }, - }); - }, - - // Transfer token - transfer: async (tokenId: string, to: string) => { - return this.callService('chain', '/transfer', { - method: 'POST', - body: { tokenId, to }, - }); - }, - - // Get transaction status - getTransaction: async (txHash: string) => { - return this.callService('chain', `/transactions/${txHash}`, { - method: 'GET', - }); - }, - }); - } - - /** - * AI Services - Vectorize and Workers AI - */ - async ai() { - if (!this.config.ai?.enabled) { - throw new Error('AI services not enabled'); - } - - return { - // Vectorize operations - vectorize: this.config.ai.vectorize?.enabled ? { - upsert: async (vectors: any[]) => { - return this.callAIService('vectorize', '/upsert', { - method: 'POST', - body: { vectors }, - }); - }, - - query: async (vector: number[], topK: number = 10) => { - return this.callAIService('vectorize', '/query', { - method: 'POST', - body: { vector, topK }, - }); - }, - - delete: async (ids: string[]) => { - return this.callAIService('vectorize', '/delete', { - method: 'POST', - body: { ids }, - }); - }, - } : null, - - // Workers AI operations - workers: this.config.ai.workers?.enabled ? { - run: async (model: string, input: any) => { - return this.callAIService('workers', '/run', { - method: 'POST', - body: { model, input }, - }); - }, - } : null, - }; - } - - // Private implementation methods - - private async initializeServices(): Promise { - console.log('🔧 Initializing ChittyChain services...'); - - for (const [serviceName, serviceConfig] of Object.entries(this.config.services)) { - if (serviceConfig?.enabled) { - console.log(` • ${serviceName}: ${serviceConfig.domain || 'localhost'}`); - - // Store service configuration - this.services.set(serviceName, { - config: serviceConfig, - baseUrl: serviceConfig.domain ? `https://${serviceConfig.domain}` : 'http://localhost:8080', - apiKey: serviceConfig.apiKey || process.env.CHITTY_CLOUD_API_KEY, - }); - } - } - } - - private async initializeAI(): Promise { - console.log('🤖 Initializing AI services...'); - - if (this.config.ai?.vectorize?.enabled) { - console.log(' • Vectorize: enabled'); - } - - if (this.config.ai?.workers?.enabled) { - console.log(' • Workers AI: enabled'); - } - } - - private async performHealthChecks(): Promise { - console.log('🏥 Performing health checks...'); - - const healthPromises = Array.from(this.services.entries()).map( - async ([serviceName, serviceInfo]) => { - try { - await this.checkServiceHealth(serviceName, serviceInfo.config); - console.log(` ✅ ${serviceName}: healthy`); - } catch (error) { - console.log(` ⚠️ ${serviceName}: degraded`); - } - } - ); - - await Promise.allSettled(healthPromises); - } - - private async checkServiceHealth(serviceName: string, config: any): Promise { - const service = this.services.get(serviceName); - if (!service) return 'offline'; - - try { - const response = await fetch(`${service.baseUrl}/health`, { - method: 'GET', - headers: service.apiKey ? { - 'Authorization': `Bearer ${service.apiKey}`, - } : {}, - signal: AbortSignal.timeout(5000), // 5 second timeout - }); - - if (response.ok) { - const data = await response.json(); - return data.status === 'healthy' ? 'online' : 'degraded'; - } - - return 'degraded'; - } catch (error) { - return 'offline'; - } - } - - private getServiceProxy(serviceName: string, methods: any) { - if (!this.services.has(serviceName)) { - throw new Error(`Service ${serviceName} not enabled or not found`); - } - - return methods; - } - - private async callService(serviceName: string, endpoint: string, options: any) { - const service = this.services.get(serviceName); - if (!service) { - throw new Error(`Service ${serviceName} not available`); - } - - const url = `${service.baseUrl}${endpoint}`; - const headers = { - 'Content-Type': 'application/json', - ...(service.apiKey && { 'Authorization': `Bearer ${service.apiKey}` }), - }; - - try { - const response = await fetch(url, { - ...options, - headers, - body: options.body ? JSON.stringify(options.body) : undefined, - }); - - if (!response.ok) { - throw new Error(`Service ${serviceName} returned ${response.status}: ${response.statusText}`); - } - - return await response.json(); - } catch (error) { - console.error(`Error calling ${serviceName} service:`, error); - throw error; - } - } - - private async callAIService(service: string, endpoint: string, options: any) { - // Placeholder for AI service calls - would integrate with Cloudflare AI APIs - throw new Error(`AI service ${service} not yet implemented`); - } -} - -/** - * Factory function to create and initialize ChittyCloudflare Core - */ -export async function createChittyCore(config: ChittyCloudflareConfig): Promise { - const core = new ChittyCloudflareCore(config); - await core.initialize(); - return core; -} - -/** - * Default configuration for development - */ -export const defaultConfig: ChittyCloudflareConfig = { - services: { - schema: { enabled: true, domain: 'schema.chitty.cc' }, - id: { enabled: true, domain: 'id.chitty.cc' }, - assets: { enabled: true, domain: 'assets.chitty.cc' }, - trust: { enabled: true, domain: 'trust.chitty.cc' }, - resolution: { enabled: true, domain: 'resolution.chitty.cc' }, - file: { enabled: true, domain: 'file.chitty.cc' }, - chain: { enabled: true, domain: 'chain.chitty.cc' }, - }, - ai: { - enabled: true, - vectorize: { enabled: true, indexName: 'chitty-assets' }, - workers: { enabled: true, scriptName: 'chitty-ai-worker' }, - }, - cloudflare: { - accountId: process.env.CLOUDFLARE_ACCOUNT_ID, - apiToken: process.env.CLOUDFLARE_API_TOKEN, - zone: process.env.CLOUDFLARE_ZONE_ID, - }, -}; \ No newline at end of file diff --git a/server/chittyCore.ts b/server/chittyCore.ts deleted file mode 100644 index e22b403..0000000 --- a/server/chittyCore.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { ChittyCloudflareCore, createChittyCore, type ChittyCloudflareConfig } from './chittyCloudflareCore'; -import { chittyOSEcosystemConfig, ChittyEvidenceLedger, createEvidenceLedger } from './chittyEcosystem'; - -/** - * ChittyOS Cloudflare Core configuration for ChittyAssets - * This provides the interface you requested: - * - * import { ChittyCloudflareCore } from '@chittyos/cloudflare-core'; - * const chitty = new ChittyCloudflareCore({ ... }); - * await chitty.initialize(); - */ - -// Use the complete ChittyOS ecosystem configuration -const chittyConfig = chittyOSEcosystemConfig; - -// Global ChittyCore instance -let chittyInstance: ChittyCloudflareCore | null = null; - -/** - * Initialize ChittyCloudflare Core singleton - */ -export async function initializeChittyCore(): Promise { - if (chittyInstance) { - return chittyInstance; - } - - console.log('🚀 Initializing ChittyOS Cloudflare Core...'); - - try { - // Create and initialize the core instance - chittyInstance = new ChittyCloudflareCore(chittyConfig); - await chittyInstance.initialize(); - - console.log('✅ ChittyOS Cloudflare Core ready'); - return chittyInstance; - - } catch (error) { - console.error('❌ Failed to initialize ChittyOS Cloudflare Core:', error); - - // Fall back to basic functionality if Cloudflare services are unavailable - console.log('🔄 Falling back to local-only mode...'); - chittyInstance = new ChittyCloudflareCore({ - services: { - // Disable all remote services for fallback - schema: { enabled: false }, - id: { enabled: false }, - assets: { enabled: false }, - trust: { enabled: false }, - resolution: { enabled: false }, - file: { enabled: false }, - chain: { enabled: false }, - }, - ai: { enabled: false }, - }); - - // Don't call initialize() for fallback mode - console.log('⚠️ Running in local-only mode - some features may be limited'); - return chittyInstance; - } -} - -/** - * Get the ChittyCore instance (must be initialized first) - */ -export function getChittyCore(): ChittyCloudflareCore { - if (!chittyInstance) { - throw new Error('ChittyCore not initialized. Call initializeChittyCore() first.'); - } - return chittyInstance; -} - -/** - * Convenient service accessors - */ -export async function getChittyServices() { - const core = getChittyCore(); - - return { - schema: await core.schema(), - id: await core.id(), - assets: await core.assets(), - trust: await core.trust(), - resolution: await core.resolution(), - file: await core.file(), - chain: await core.chain(), - ai: await core.ai(), - - // Evidence Ledger (Our specialized service) - evidenceLedger: new ChittyEvidenceLedger(core), - - // Utility methods - getEcosystemStatus: () => core.getEcosystemStatus(), - }; -} - -/** - * Get Evidence Ledger instance - */ -export async function getEvidenceLedger(): Promise { - const services = await getChittyServices(); - return services.evidenceLedger; -} - -/** - * Export the main class for the interface you requested - * This allows: import { ChittyCloudflareCore } from '@chittyos/cloudflare-core'; - */ -export { ChittyCloudflareCore } from './chittyCloudflareCore'; \ No newline at end of file diff --git a/server/chittyEcosystem.ts b/server/chittyEcosystem.ts deleted file mode 100644 index aa713a3..0000000 --- a/server/chittyEcosystem.ts +++ /dev/null @@ -1,303 +0,0 @@ -/** - * ChittyOS Complete Ecosystem Integration - * Evidence Ledger as part of the broader ChittyOS platform - */ - -import { ChittyCloudflareCore, type ChittyCloudflareConfig } from './chittyCloudflareCore'; -import { z } from 'zod'; - -/** - * ChittyOS Ecosystem Service Map - * Based on the official service domains - */ -export const ChittyOSServices = { - // Core Platform Services - ID: 'id.chitty.cc', // ✅ ChittyID generation (working) - SCHEMA: 'schema.chitty.cc', // Schema registry & data models - CHAIN: 'chain.chitty.cc', // ChittyChain blockchain for immutability - LEDGER: 'ledger.chitty.cc', // Evidence ledger (what we built!) - TRUST: 'trust.chitty.cc', // Trust scoring & reputation - VERIFY: 'verify.chitty.cc', // Verification & authentication -} as const; - -/** - * Evidence Ledger Schema for ChittyOS - */ -export const EvidenceLedgerSchema = z.object({ - chittyId: z.string().uuid(), - namespace: z.string().default('evidence-ledger'), - region: z.number().default(1), - jurisdiction: z.string().default('USA'), - trustLevel: z.number().min(1).max(5).default(3), - - // Evidence metadata - evidenceType: z.enum(['document', 'photo', 'video', 'audio', 'digital', 'physical']), - retentionDays: z.number().default(2555), // 7 years - encryption: z.string().default('AES-256-GCM'), - - // Legal framework - legalFramework: z.string().default('USA_FEDERAL'), - evidenceStandards: z.string().default('FRE'), // Federal Rules of Evidence - chainOfCustody: z.enum(['strict', 'standard', 'basic']).default('strict'), - digitalSignatureRequired: z.boolean().default(true), -}); - -/** - * Complete ChittyOS Ecosystem Configuration - */ -export const chittyOSEcosystemConfig: ChittyCloudflareConfig = { - services: { - // Core ChittyOS Platform Services - schema: { - enabled: true, - domain: ChittyOSServices.SCHEMA, - apiKey: process.env.CHITTY_SCHEMA_API_KEY, - }, - id: { - enabled: true, - domain: ChittyOSServices.ID, - apiKey: process.env.CHITTY_ID_API_KEY, - }, - chain: { - enabled: true, - domain: ChittyOSServices.CHAIN, - apiKey: process.env.CHITTY_CHAIN_API_KEY, - }, - trust: { - enabled: true, - domain: ChittyOSServices.TRUST, - apiKey: process.env.CHITTY_TRUST_API_KEY, - }, - - // Evidence Ledger Services (Our Domain) - assets: { - enabled: true, - domain: ChittyOSServices.LEDGER, - apiKey: process.env.CHITTY_LEDGER_API_KEY, - }, - file: { - enabled: true, - domain: ChittyOSServices.LEDGER, - apiKey: process.env.CHITTY_LEDGER_API_KEY, - }, - - // Verification & Authentication - resolution: { - enabled: true, - domain: ChittyOSServices.VERIFY, - apiKey: process.env.CHITTY_VERIFY_API_KEY, - }, - }, - - // AI Services for Evidence Analysis - ai: { - enabled: true, - vectorize: { - enabled: true, - indexName: 'chitty-evidence-vectors', - }, - workers: { - enabled: true, - scriptName: 'chitty-evidence-ai', - }, - }, - - // Cloudflare Edge Configuration - cloudflare: { - accountId: process.env.CLOUDFLARE_ACCOUNT_ID, - apiToken: process.env.CLOUDFLARE_API_TOKEN, - zone: process.env.CLOUDFLARE_ZONE_ID, - }, -}; - -/** - * Evidence Ledger Integration Service - * Specialized service for evidence management within ChittyOS - */ -export class ChittyEvidenceLedger { - private core: ChittyCloudflareCore; - private config: typeof EvidenceLedgerSchema._type; - - constructor(core: ChittyCloudflareCore) { - this.core = core; - this.config = { - namespace: process.env.CHITTY_NAMESPACE || 'evidence-ledger', - region: parseInt(process.env.CHITTY_REGION || '1'), - jurisdiction: process.env.CHITTY_JURISDICTION || 'USA', - trustLevel: parseInt(process.env.CHITTY_TRUST_LEVEL || '3'), - retentionDays: parseInt(process.env.CHITTY_EVIDENCE_RETENTION_DAYS || '2555'), - encryption: process.env.CHITTY_EVIDENCE_ENCRYPTION || 'AES-256-GCM', - legalFramework: process.env.CHITTY_LEGAL_FRAMEWORK || 'USA_FEDERAL', - evidenceStandards: process.env.CHITTY_EVIDENCE_STANDARDS || 'FRE', - chainOfCustody: (process.env.CHITTY_CHAIN_OF_CUSTODY as any) || 'strict', - digitalSignatureRequired: process.env.CHITTY_DIGITAL_SIGNATURE_REQUIRED === 'true', - } as any; - } - - /** - * Submit evidence to the ChittyOS Evidence Ledger - */ - async submitEvidence(evidence: { - chittyId?: string; - evidenceType: string; - data: any; - metadata: any; - submitterId: string; - }) { - // Generate ChittyID if not provided - const services = await this.getServices(); - const chittyId = evidence.chittyId || (await services.id.generate('evidence')).id; - - // Validate evidence schema - const validatedEvidence = EvidenceLedgerSchema.parse({ - chittyId, - evidenceType: evidence.evidenceType, - ...this.config, - }); - - // Submit to schema service for validation - await services.schema.validate('evidence-v1', { - ...validatedEvidence, - data: evidence.data, - metadata: evidence.metadata, - }); - - // Store in evidence ledger - const ledgerResult = await services.assets.register({ - chittyId, - type: 'evidence', - data: evidence.data, - metadata: { - ...evidence.metadata, - submitterId: evidence.submitterId, - submissionTimestamp: new Date().toISOString(), - jurisdiction: this.config.jurisdiction, - legalFramework: this.config.legalFramework, - }, - }); - - // Calculate trust score - const trustScore = await services.trust.calculate(chittyId, { - evidenceType: evidence.evidenceType, - submitterId: evidence.submitterId, - metadata: evidence.metadata, - }); - - // Mint to blockchain for immutability - const chainResult = await services.chain.mint(chittyId, { - evidenceHash: ledgerResult.hash, - trustScore: trustScore.score, - timestamp: new Date().toISOString(), - }); - - return { - chittyId, - ledgerResult, - trustScore, - chainResult, - status: 'submitted', - retentionUntil: new Date(Date.now() + this.config.retentionDays * 24 * 60 * 60 * 1000), - }; - } - - /** - * Retrieve evidence by ChittyID - */ - async getEvidence(chittyId: string) { - const services = await this.getServices(); - - // Get from ledger - const evidence = await services.assets.get(chittyId); - - // Get trust score - const trustScore = await services.trust.history(chittyId); - - // Get blockchain verification - const chainVerification = await services.chain.getTransaction(evidence.transactionHash); - - return { - evidence, - trustScore, - chainVerification, - jurisdiction: this.config.jurisdiction, - legalFramework: this.config.legalFramework, - }; - } - - /** - * Verify evidence authenticity - */ - async verifyEvidence(chittyId: string) { - const services = await this.getServices(); - - // Multi-layer verification - const results = await Promise.all([ - services.verify.verify(chittyId, { method: 'blockchain' }), - services.trust.calculate(chittyId), - services.chain.getTransaction(chittyId), - ]); - - const [blockchainVerif, trustVerif, chainData] = results; - - return { - isAuthentic: blockchainVerif.verified && trustVerif.trustScore >= this.config.trustLevel, - blockchainVerification: blockchainVerif, - trustVerification: trustVerif, - chainData, - complianceLevel: this.calculateComplianceLevel(results), - }; - } - - /** - * Get ecosystem status for evidence ledger - */ - async getEcosystemStatus() { - const status = await this.core.getEcosystemStatus(); - - return { - ...status, - evidenceLedger: { - status: status.assets, // Evidence ledger runs on assets service - namespace: this.config.namespace, - region: this.config.region, - jurisdiction: this.config.jurisdiction, - legalFramework: this.config.legalFramework, - retentionPolicy: `${this.config.retentionDays} days`, - encryption: this.config.encryption, - }, - }; - } - - private async getServices() { - return { - schema: await this.core.schema(), - id: await this.core.id(), - assets: await this.core.assets(), - trust: await this.core.trust(), - chain: await this.core.chain(), - verify: await this.core.resolution(), // Using resolution service for verification - }; - } - - private calculateComplianceLevel(verificationResults: any[]): 'full' | 'partial' | 'minimal' { - const [blockchain, trust, chain] = verificationResults; - - if (blockchain.verified && trust.trustScore >= 4 && chain.confirmed) { - return 'full'; - } else if (blockchain.verified && trust.trustScore >= 2) { - return 'partial'; - } else { - return 'minimal'; - } - } -} - -/** - * Create Evidence Ledger instance with ChittyOS ecosystem integration - */ -export async function createEvidenceLedger(): Promise { - const core = new ChittyCloudflareCore(chittyOSEcosystemConfig); - await core.initialize(); - - return new ChittyEvidenceLedger(core); -} \ No newline at end of file diff --git a/server/db.ts b/server/db.ts deleted file mode 100644 index 7ca3d56..0000000 --- a/server/db.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Pool, neonConfig } from '@neondatabase/serverless'; -import { drizzle } from 'drizzle-orm/neon-serverless'; -import ws from "ws"; -import * as schema from "@shared/schema"; - -neonConfig.webSocketConstructor = ws; - -if (!process.env.DATABASE_URL) { - throw new Error( - "DATABASE_URL must be set. Did you forget to provision a database?", - ); -} - -export const pool = new Pool({ connectionString: process.env.DATABASE_URL }); -export const db = drizzle({ client: pool, schema }); \ No newline at end of file diff --git a/server/githubWebhooks.ts b/server/githubWebhooks.ts deleted file mode 100644 index 97ac23d..0000000 --- a/server/githubWebhooks.ts +++ /dev/null @@ -1,343 +0,0 @@ -/** - * GitHub App Webhook Handler for ChittyAssets - * Processes GitHub events and triggers appropriate actions - */ - -import crypto from 'crypto'; -import express, { type Request, type Response, type NextFunction, type Express } from 'express'; -import { storage } from './storage'; - -interface GitHubWebhookPayload { - action?: string; - repository?: { - id: number; - name: string; - full_name: string; - owner: { - login: string; - }; - }; - sender?: { - login: string; - id: number; - }; - installation?: { - id: number; - }; - pull_request?: any; - issue?: any; - workflow_run?: any; - check_run?: any; -} - -export class GitHubWebhookHandler { - private webhookSecret: string; - - constructor(webhookSecret: string) { - this.webhookSecret = webhookSecret; - } - - /** - * Verify webhook signature - */ - private verifySignature(payload: string, signature: string | undefined): boolean { - if (!signature) return false; - - const hmac = crypto.createHmac('sha256', this.webhookSecret); - const digest = 'sha256=' + hmac.update(payload).digest('hex'); - - return crypto.timingSafeEqual( - Buffer.from(signature), - Buffer.from(digest) - ); - } - - /** - * Main webhook handler middleware - */ - public handleWebhook = async (req: Request, res: Response, next: NextFunction) => { - try { - const signature = req.headers['x-hub-signature-256'] as string; - const event = req.headers['x-github-event'] as string; - const delivery = req.headers['x-github-delivery'] as string; - - // Verify signature - const payload = JSON.stringify(req.body); - if (!this.verifySignature(payload, signature)) { - console.error('Invalid webhook signature'); - return res.status(401).json({ error: 'Invalid signature' }); - } - - console.log(`📨 GitHub webhook received: ${event} (${delivery})`); - - // Process the webhook based on event type - await this.processWebhook(event, req.body as GitHubWebhookPayload); - - res.status(200).json({ received: true }); - } catch (error) { - console.error('Webhook processing error:', error); - res.status(500).json({ error: 'Webhook processing failed' }); - } - }; - - /** - * Process webhook based on event type - */ - private async processWebhook(event: string, payload: GitHubWebhookPayload): Promise { - switch (event) { - case 'push': - await this.handlePush(payload); - break; - - case 'pull_request': - await this.handlePullRequest(payload); - break; - - case 'issues': - await this.handleIssue(payload); - break; - - case 'workflow_run': - await this.handleWorkflowRun(payload); - break; - - case 'check_run': - await this.handleCheckRun(payload); - break; - - case 'installation': - await this.handleInstallation(payload); - break; - - case 'repository_dispatch': - await this.handleRepositoryDispatch(payload); - break; - - default: - console.log(`Unhandled event type: ${event}`); - } - } - - /** - * Handle push events - */ - private async handlePush(payload: GitHubWebhookPayload): Promise { - console.log(`🚀 Push to ${payload.repository?.full_name}`); - - // Trigger Notion sync on push to main - if (payload.repository?.full_name === 'chittyos/chittyassets') { - await this.triggerNotionSync(); - } - - // Log activity - await this.logActivity('push', payload); - } - - /** - * Handle pull request events - */ - private async handlePullRequest(payload: GitHubWebhookPayload): Promise { - const action = payload.action; - const pr = payload.pull_request; - - console.log(`🔄 Pull request ${action}: #${pr?.number}`); - - // Auto-label based on files changed - if (action === 'opened' || action === 'synchronize') { - await this.autoLabelPullRequest(pr); - } - - // Run security checks - if (action === 'opened') { - await this.runSecurityChecks(pr); - } - - await this.logActivity('pull_request', payload); - } - - /** - * Handle issue events - */ - private async handleIssue(payload: GitHubWebhookPayload): Promise { - const action = payload.action; - const issue = payload.issue; - - console.log(`📋 Issue ${action}: #${issue?.number}`); - - // Auto-respond to new issues - if (action === 'opened') { - await this.autoRespondToIssue(issue); - } - - await this.logActivity('issue', payload); - } - - /** - * Handle workflow run events - */ - private async handleWorkflowRun(payload: GitHubWebhookPayload): Promise { - const run = payload.workflow_run; - - console.log(`⚙️ Workflow ${run?.name}: ${run?.status}`); - - // Send notifications for failed workflows - if (run?.conclusion === 'failure') { - await this.notifyWorkflowFailure(run); - } - - await this.logActivity('workflow_run', payload); - } - - /** - * Handle check run events - */ - private async handleCheckRun(payload: GitHubWebhookPayload): Promise { - const check = payload.check_run; - - console.log(`✅ Check run ${check?.name}: ${check?.status}`); - - await this.logActivity('check_run', payload); - } - - /** - * Handle installation events - */ - private async handleInstallation(payload: GitHubWebhookPayload): Promise { - const action = payload.action; - - console.log(`🔧 App installation ${action}`); - - if (action === 'created') { - await this.onAppInstalled(payload); - } else if (action === 'deleted') { - await this.onAppUninstalled(payload); - } - - await this.logActivity('installation', payload); - } - - /** - * Handle repository dispatch events - */ - private async handleRepositoryDispatch(payload: any): Promise { - const eventType = payload.event_type; - - console.log(`📡 Repository dispatch: ${eventType}`); - - // Handle custom events - switch (eventType) { - case 'deploy': - await this.triggerDeployment(payload.client_payload); - break; - case 'sync': - await this.triggerNotionSync(); - break; - default: - console.log(`Unknown dispatch event: ${eventType}`); - } - - await this.logActivity('repository_dispatch', payload); - } - - /** - * Helper functions - */ - - private async triggerNotionSync(): Promise { - console.log('🔄 Triggering Notion sync...'); - // Trigger the Notion sync workflow - // This would call the GitHub API to trigger the workflow - } - - private async autoLabelPullRequest(pr: any): Promise { - console.log(`🏷️ Auto-labeling PR #${pr?.number}`); - // Analyze changed files and add appropriate labels - } - - private async runSecurityChecks(pr: any): Promise { - console.log(`🔒 Running security checks for PR #${pr?.number}`); - // Trigger security scanning workflows - } - - private async autoRespondToIssue(issue: any): Promise { - console.log(`💬 Auto-responding to issue #${issue?.number}`); - // Post welcome message or categorize issue - } - - private async notifyWorkflowFailure(run: any): Promise { - console.log(`⚠️ Notifying about workflow failure: ${run?.name}`); - // Send notifications via Slack/Discord/email - } - - private async onAppInstalled(payload: GitHubWebhookPayload): Promise { - console.log(`✨ App installed on ${payload.repository?.full_name}`); - // Initialize repository settings - } - - private async onAppUninstalled(payload: GitHubWebhookPayload): Promise { - console.log(`👋 App uninstalled from ${payload.repository?.full_name}`); - // Clean up repository data - } - - private async triggerDeployment(payload: any): Promise { - console.log(`🚀 Triggering deployment: ${payload?.environment}`); - // Trigger deployment workflow - } - - private async logActivity(event: string, payload: GitHubWebhookPayload): Promise { - // Log webhook activity for audit trail - const activity = { - event, - repository: payload.repository?.full_name, - sender: payload.sender?.login, - timestamp: new Date().toISOString(), - installation_id: payload.installation?.id, - }; - - console.log('📝 Activity logged:', activity); - // Store in database if needed - } -} - -/** - * Setup GitHub webhook routes - */ -export function setupGitHubWebhooks(app: Express): void { - const webhookSecret = process.env.GITHUB_APP_WEBHOOK_SECRET; - - if (!webhookSecret) { - console.warn('⚠️ GITHUB_APP_WEBHOOK_SECRET not configured'); - return; - } - - const handler = new GitHubWebhookHandler(webhookSecret); - - // GitHub webhook endpoint - app.post('/api/github/webhooks', express.raw({ type: 'application/json' }), handler.handleWebhook); - - // GitHub App callback (OAuth flow) - app.get('/api/github/callback', async (req, res) => { - const { code, state } = req.query; - - if (!code) { - return res.status(400).json({ error: 'Missing code parameter' }); - } - - // Exchange code for access token - // This would implement OAuth flow - console.log('GitHub OAuth callback received'); - - res.redirect('/dashboard?github=connected'); - }); - - // GitHub App setup endpoint - app.get('/api/github/setup', async (req, res) => { - res.json({ - message: 'ChittyAssets GitHub App Setup', - status: 'ready', - version: '1.0.0', - }); - }); - - console.log('✅ GitHub webhooks configured'); -} \ No newline at end of file diff --git a/server/index.ts b/server/index.ts deleted file mode 100644 index 8bf1912..0000000 --- a/server/index.ts +++ /dev/null @@ -1,71 +0,0 @@ -import express, { type Request, Response, NextFunction } from "express"; -import { registerRoutes } from "./routes"; -import { setupVite, serveStatic, log } from "./vite"; - -const app = express(); -app.use(express.json()); -app.use(express.urlencoded({ extended: false })); - -app.use((req, res, next) => { - const start = Date.now(); - const path = req.path; - let capturedJsonResponse: Record | undefined = undefined; - - const originalResJson = res.json; - res.json = function (bodyJson, ...args) { - capturedJsonResponse = bodyJson; - return originalResJson.apply(res, [bodyJson, ...args]); - }; - - res.on("finish", () => { - const duration = Date.now() - start; - if (path.startsWith("/api")) { - let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`; - if (capturedJsonResponse) { - logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`; - } - - if (logLine.length > 80) { - logLine = logLine.slice(0, 79) + "…"; - } - - log(logLine); - } - }); - - next(); -}); - -(async () => { - const server = await registerRoutes(app); - - app.use((err: any, _req: Request, res: Response, _next: NextFunction) => { - const status = err.status || err.statusCode || 500; - const message = err.message || "Internal Server Error"; - - res.status(status).json({ message }); - throw err; - }); - - // importantly only setup vite in development and after - // setting up all the other routes so the catch-all route - // doesn't interfere with the other routes - if (app.get("env") === "development") { - await setupVite(app, server); - } else { - serveStatic(app); - } - - // ALWAYS serve the app on the port specified in the environment variable PORT - // Other ports are firewalled. Default to 5000 if not specified. - // this serves both the API and the client. - // It is the only port that is not firewalled. - const port = parseInt(process.env.PORT || '5000', 10); - server.listen({ - port, - host: "0.0.0.0", - reusePort: true, - }, () => { - log(`serving on port ${port}`); - }); -})(); diff --git a/server/middleware/errorHandler.ts b/server/middleware/errorHandler.ts deleted file mode 100644 index a897cf7..0000000 --- a/server/middleware/errorHandler.ts +++ /dev/null @@ -1,180 +0,0 @@ -import type { Request, Response, NextFunction, ErrorRequestHandler } from 'express'; - -/** - * Standard API Error class for consistent error handling - */ -export class APIError extends Error { - constructor( - message: string, - public statusCode: number = 500, - public code: string = 'INTERNAL_ERROR', - public details?: any - ) { - super(message); - this.name = 'APIError'; - Error.captureStackTrace(this, this.constructor); - } -} - -/** - * Common error types for convenience - */ -export class ValidationError extends APIError { - constructor(message: string, details?: any) { - super(message, 400, 'VALIDATION_ERROR', details); - } -} - -export class AuthenticationError extends APIError { - constructor(message: string = 'Authentication required') { - super(message, 401, 'AUTHENTICATION_ERROR'); - } -} - -export class AuthorizationError extends APIError { - constructor(message: string = 'Insufficient permissions') { - super(message, 403, 'AUTHORIZATION_ERROR'); - } -} - -export class NotFoundError extends APIError { - constructor(resource: string = 'Resource') { - super(`${resource} not found`, 404, 'NOT_FOUND'); - } -} - -export class ConflictError extends APIError { - constructor(message: string) { - super(message, 409, 'CONFLICT'); - } -} - -export class RateLimitError extends APIError { - constructor(message: string = 'Rate limit exceeded') { - super(message, 429, 'RATE_LIMIT_EXCEEDED'); - } -} - -/** - * Standard API response interface - */ -export interface APIResponse { - success: boolean; - data?: T; - error?: { - code: string; - message: string; - details?: any; - }; - meta?: { - requestId?: string; - timestamp?: string; - }; -} - -/** - * Helper function to create success responses - */ -export function createSuccessResponse(data: T, meta?: any): APIResponse { - return { - success: true, - data, - meta: { - timestamp: new Date().toISOString(), - ...meta, - }, - }; -} - -/** - * Helper function to create error responses - */ -export function createErrorResponse( - error: APIError | Error, - requestId?: string -): APIResponse { - const apiError = error instanceof APIError ? error : new APIError(error.message); - - return { - success: false, - error: { - code: apiError.code, - message: apiError.message, - details: apiError.details, - }, - meta: { - requestId, - timestamp: new Date().toISOString(), - }, - }; -} - -/** - * Centralized error handling middleware - */ -export const errorHandler: ErrorRequestHandler = ( - err: Error, - req: Request, - res: Response, - next: NextFunction -) => { - // Generate request ID for tracking - const requestId = req.headers['x-request-id'] as string || - `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - - // Convert to APIError if it's not already - const apiError = err instanceof APIError ? err : new APIError( - process.env.NODE_ENV === 'production' ? 'Internal Server Error' : err.message, - 500, - 'INTERNAL_ERROR' - ); - - // Log error details (in production, use proper logging service) - const logLevel = apiError.statusCode >= 500 ? 'error' : 'warn'; - console[logLevel](`[${requestId}] ${apiError.code}: ${apiError.message}`, { - statusCode: apiError.statusCode, - method: req.method, - url: req.url, - userAgent: req.headers['user-agent'], - stack: process.env.NODE_ENV === 'development' ? err.stack : undefined, - details: apiError.details, - }); - - // Send standardized error response - res.status(apiError.statusCode).json(createErrorResponse(apiError, requestId)); -}; - -/** - * Async error wrapper - catches async errors and passes them to error handler - */ -export function asyncHandler(fn: Function) { - return (req: Request, res: Response, next: NextFunction) => { - Promise.resolve(fn(req, res, next)).catch(next); - }; -} - -/** - * 404 handler for unmatched routes - */ -export function notFoundHandler(req: Request, res: Response) { - const error = new NotFoundError('Endpoint'); - res.status(404).json(createErrorResponse(error)); -} - -/** - * Request validation middleware generator - */ -export function validateRequest(schema: any, source: 'body' | 'query' | 'params' = 'body') { - return (req: Request, res: Response, next: NextFunction) => { - try { - const result = schema.safeParse(req[source]); - if (!result.success) { - throw new ValidationError('Invalid request data', result.error.issues); - } - req[source] = result.data; - next(); - } catch (error) { - next(error); - } - }; -} \ No newline at end of file diff --git a/server/middleware/logging.ts b/server/middleware/logging.ts deleted file mode 100644 index cb2d236..0000000 --- a/server/middleware/logging.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { Request, Response, NextFunction } from 'express'; - -/** - * Request logging middleware with performance tracking - */ -export function requestLogger(req: Request, res: Response, next: NextFunction) { - const start = Date.now(); - const requestId = req.headers['x-request-id'] as string || - `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - - // Attach request ID to request for use in other middleware - req.headers['x-request-id'] = requestId; - - // Log request start - if (req.path.startsWith('/api')) { - console.log(`[${requestId}] ${req.method} ${req.path} - Start`, { - userAgent: req.headers['user-agent'], - ip: req.ip, - query: req.query, - }); - } - - // Capture response details - let capturedJsonResponse: Record | undefined = undefined; - - const originalResJson = res.json; - res.json = function (bodyJson, ...args) { - capturedJsonResponse = bodyJson; - return originalResJson.apply(res, [bodyJson, ...args]); - }; - - res.on('finish', () => { - const duration = Date.now() - start; - - if (req.path.startsWith('/api')) { - let logLine = `[${requestId}] ${req.method} ${req.path} ${res.statusCode} in ${duration}ms`; - - // Add response summary for successful responses - if (capturedJsonResponse && res.statusCode < 400) { - if (capturedJsonResponse.success !== undefined) { - logLine += ` :: ${JSON.stringify({ success: capturedJsonResponse.success })}`; - } else { - logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`; - } - } - - // Add error details for failed responses - if (capturedJsonResponse && res.statusCode >= 400) { - logLine += ` :: ${JSON.stringify({ - error: capturedJsonResponse.error?.code || 'UNKNOWN_ERROR' - })}`; - } - - if (logLine.length > 120) { - logLine = logLine.slice(0, 119) + '…'; - } - - const logLevel = res.statusCode >= 500 ? 'error' : - res.statusCode >= 400 ? 'warn' : 'info'; - console[logLevel](logLine); - } - }); - - next(); -} - -/** - * Enhanced console log function that formats logs consistently - */ -export function log(message: string, source = 'express', level: 'info' | 'warn' | 'error' = 'info') { - const formattedTime = new Date().toLocaleTimeString('en-US', { - hour: 'numeric', - minute: '2-digit', - second: '2-digit', - hour12: true, - }); - - const logMessage = `${formattedTime} [${source}] ${message}`; - console[level](logMessage); -} \ No newline at end of file diff --git a/server/middleware/validation.ts b/server/middleware/validation.ts deleted file mode 100644 index 811d8fc..0000000 --- a/server/middleware/validation.ts +++ /dev/null @@ -1,208 +0,0 @@ -import type { Request, Response, NextFunction } from 'express'; -import { z } from 'zod'; -import { ValidationError } from './errorHandler'; - -/** - * Generic request validation middleware using Zod schemas - */ -export function validateRequest< - TBody = any, - TQuery = any, - TParams = any ->(schemas: { - body?: z.ZodSchema; - query?: z.ZodSchema; - params?: z.ZodSchema; -}) { - return (req: Request, res: Response, next: NextFunction) => { - try { - // Validate request body - if (schemas.body) { - const bodyResult = schemas.body.safeParse(req.body); - if (!bodyResult.success) { - throw new ValidationError('Invalid request body', { - field: 'body', - issues: bodyResult.error.issues, - }); - } - req.body = bodyResult.data; - } - - // Validate query parameters - if (schemas.query) { - const queryResult = schemas.query.safeParse(req.query); - if (!queryResult.success) { - throw new ValidationError('Invalid query parameters', { - field: 'query', - issues: queryResult.error.issues, - }); - } - req.query = queryResult.data; - } - - // Validate route parameters - if (schemas.params) { - const paramsResult = schemas.params.safeParse(req.params); - if (!paramsResult.success) { - throw new ValidationError('Invalid route parameters', { - field: 'params', - issues: paramsResult.error.issues, - }); - } - req.params = paramsResult.data; - } - - next(); - } catch (error) { - next(error); - } - }; -} - -/** - * Common validation schemas - */ -export const commonSchemas = { - // Pagination parameters - pagination: z.object({ - page: z.coerce.number().min(1).default(1), - limit: z.coerce.number().min(1).max(100).default(20), - sortBy: z.string().optional(), - sortOrder: z.enum(['asc', 'desc']).default('desc'), - }), - - // Asset ID parameter - assetId: z.object({ - assetId: z.string().uuid('Asset ID must be a valid UUID'), - }), - - // Evidence ID parameter - evidenceId: z.object({ - evidenceId: z.string().uuid('Evidence ID must be a valid UUID'), - }), - - // User ID parameter - userId: z.object({ - userId: z.string().min(1, 'User ID is required'), - }), - - // Search query - search: z.object({ - q: z.string().min(1, 'Search query is required').optional(), - type: z.string().optional(), - status: z.string().optional(), - }), - - // File upload metadata - fileMetadata: z.object({ - originalName: z.string().min(1, 'Original filename is required'), - mimeType: z.string().min(1, 'MIME type is required'), - size: z.number().min(1, 'File size must be greater than 0'), - }), - - // Date range filter - dateRange: z.object({ - startDate: z.coerce.date().optional(), - endDate: z.coerce.date().optional(), - }).refine( - (data) => !data.startDate || !data.endDate || data.startDate <= data.endDate, - { - message: 'Start date must be before or equal to end date', - path: ['dateRange'], - } - ), -}; - -/** - * Middleware to validate file uploads - */ -export function validateFileUpload(options: { - maxSize?: number; - allowedMimeTypes?: string[]; - required?: boolean; -} = {}) { - const { - maxSize = 10 * 1024 * 1024, // 10MB default - allowedMimeTypes, - required = true, - } = options; - - return (req: Request, res: Response, next: NextFunction) => { - try { - const files = req.files as Express.Multer.File[] | undefined; - const file = files?.[0]; - - if (required && !file) { - throw new ValidationError('File upload is required'); - } - - if (file) { - // Check file size - if (file.size > maxSize) { - throw new ValidationError( - `File size exceeds limit of ${maxSize / (1024 * 1024)}MB`, - { actualSize: file.size, maxSize } - ); - } - - // Check MIME type - if (allowedMimeTypes && !allowedMimeTypes.includes(file.mimetype)) { - throw new ValidationError( - `File type ${file.mimetype} is not allowed`, - { allowedTypes: allowedMimeTypes, actualType: file.mimetype } - ); - } - - // Validate file metadata - const metadataResult = commonSchemas.fileMetadata.safeParse({ - originalName: file.originalname, - mimeType: file.mimetype, - size: file.size, - }); - - if (!metadataResult.success) { - throw new ValidationError('Invalid file metadata', metadataResult.error.issues); - } - } - - next(); - } catch (error) { - next(error); - } - }; -} - -/** - * Sanitize input to prevent XSS and injection attacks - */ -export function sanitizeInput(req: Request, res: Response, next: NextFunction) { - // Basic sanitization function (in production, use a proper library like DOMPurify) - function sanitize(obj: any): any { - if (typeof obj === 'string') { - return obj - .replace(/)<[^<]*)*<\/script>/gi, '') - .replace(/javascript:/gi, '') - .replace(/on\w+\s*=/gi, ''); - } - if (Array.isArray(obj)) { - return obj.map(sanitize); - } - if (obj !== null && typeof obj === 'object') { - const sanitized: any = {}; - for (const [key, value] of Object.entries(obj)) { - sanitized[key] = sanitize(value); - } - return sanitized; - } - return obj; - } - - if (req.body) { - req.body = sanitize(req.body); - } - if (req.query) { - req.query = sanitize(req.query); - } - - next(); -} \ No newline at end of file diff --git a/server/objectAcl.ts b/server/objectAcl.ts deleted file mode 100644 index b7ec835..0000000 --- a/server/objectAcl.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { File } from "@google-cloud/storage"; - -const ACL_POLICY_METADATA_KEY = "custom:aclPolicy"; - -// The type of the access group. -// -// Can be flexibly defined according to the use case. -// -// Examples: -// - USER_LIST: the users from a list stored in the database; -// - EMAIL_DOMAIN: the users whose email is in a specific domain; -// - GROUP_MEMBER: the users who are members of a specific group; -// - SUBSCRIBER: the users who are subscribers of a specific service / content -// creator. -export enum ObjectAccessGroupType {} - -// The logic user group that can access the object. -export interface ObjectAccessGroup { - // The type of the access group. - type: ObjectAccessGroupType; - // The logic id that is enough to identify the qualified group members. - // - // It may have different format for different types. For example: - // - for USER_LIST, the id could be the user list db entity id, and the - // user list db entity could contain a bunch of user ids. User needs - // to be a member of the user list to be able to access the object. - // - for EMAIL_DOMAIN, the id could be the email domain, and the user needs - // to have an email with the domain to be able to access the object. - // - for GROUP_MEMBER, the id could be the group db entity id, and the - // group db entity could contain a bunch of user ids. User needs to be - // a member of the group to be able to access the object. - // - for SUBSCRIBER, the id could be the subscriber db entity id, and the - // subscriber db entity could contain a bunch of user ids. User needs to - // be a subscriber to be able to access the object. - id: string; -} - -export enum ObjectPermission { - READ = "read", - WRITE = "write", -} - -export interface ObjectAclRule { - group: ObjectAccessGroup; - permission: ObjectPermission; -} - -// The ACL policy of the object. -// This would be set as part of the object custom metadata: -// - key: "custom:aclPolicy" -// - value: JSON string of the ObjectAclPolicy object. -export interface ObjectAclPolicy { - owner: string; - visibility: "public" | "private"; - aclRules?: Array; -} - -// Check if the requested permission is allowed based on the granted permission. -function isPermissionAllowed( - requested: ObjectPermission, - granted: ObjectPermission, -): boolean { - // Users granted with read or write permissions can read the object. - if (requested === ObjectPermission.READ) { - return [ObjectPermission.READ, ObjectPermission.WRITE].includes(granted); - } - - // Only users granted with write permissions can write the object. - return granted === ObjectPermission.WRITE; -} - -// The base class for all access groups. -// -// Different types of access groups can be implemented according to the use case. -abstract class BaseObjectAccessGroup implements ObjectAccessGroup { - constructor( - public readonly type: ObjectAccessGroupType, - public readonly id: string, - ) {} - - // Check if the user is a member of the group. - public abstract hasMember(userId: string): Promise; -} - -function createObjectAccessGroup( - group: ObjectAccessGroup, -): BaseObjectAccessGroup { - switch (group.type) { - // Implement the case for each type of access group to instantiate. - // - // For example: - // case "USER_LIST": - // return new UserListAccessGroup(group.id); - // case "EMAIL_DOMAIN": - // return new EmailDomainAccessGroup(group.id); - // case "GROUP_MEMBER": - // return new GroupMemberAccessGroup(group.id); - // case "SUBSCRIBER": - // return new SubscriberAccessGroup(group.id); - default: - throw new Error(`Unknown access group type: ${group.type}`); - } -} - -// Sets the ACL policy to the object metadata. -export async function setObjectAclPolicy( - objectFile: File, - aclPolicy: ObjectAclPolicy, -): Promise { - const [exists] = await objectFile.exists(); - if (!exists) { - throw new Error(`Object not found: ${objectFile.name}`); - } - - await objectFile.setMetadata({ - metadata: { - [ACL_POLICY_METADATA_KEY]: JSON.stringify(aclPolicy), - }, - }); -} - -// Gets the ACL policy from the object metadata. -export async function getObjectAclPolicy( - objectFile: File, -): Promise { - const [metadata] = await objectFile.getMetadata(); - const aclPolicy = metadata?.metadata?.[ACL_POLICY_METADATA_KEY]; - if (!aclPolicy) { - return null; - } - return JSON.parse(aclPolicy as string); -} - -// Checks if the user can access the object. -export async function canAccessObject({ - userId, - objectFile, - requestedPermission, -}: { - userId?: string; - objectFile: File; - requestedPermission: ObjectPermission; -}): Promise { - // When this function is called, the acl policy is required. - const aclPolicy = await getObjectAclPolicy(objectFile); - if (!aclPolicy) { - return false; - } - - // Public objects are always accessible for read. - if ( - aclPolicy.visibility === "public" && - requestedPermission === ObjectPermission.READ - ) { - return true; - } - - // Access control requires the user id. - if (!userId) { - return false; - } - - // The owner of the object can always access it. - if (aclPolicy.owner === userId) { - return true; - } - - // Go through the ACL rules to check if the user has the required permission. - for (const rule of aclPolicy.aclRules || []) { - const accessGroup = createObjectAccessGroup(rule.group); - if ( - (await accessGroup.hasMember(userId)) && - isPermissionAllowed(requestedPermission, rule.permission) - ) { - return true; - } - } - - return false; -} diff --git a/server/objectStorage.ts b/server/objectStorage.ts deleted file mode 100644 index 2039f42..0000000 --- a/server/objectStorage.ts +++ /dev/null @@ -1,299 +0,0 @@ -import { Storage, File } from "@google-cloud/storage"; -import { Response } from "express"; -import { randomUUID } from "crypto"; -import { - ObjectAclPolicy, - ObjectPermission, - canAccessObject, - getObjectAclPolicy, - setObjectAclPolicy, -} from "./objectAcl"; - -const REPLIT_SIDECAR_ENDPOINT = "http://127.0.0.1:1106"; - -// The object storage client is used to interact with the object storage service. -export const objectStorageClient = new Storage({ - credentials: { - audience: "replit", - subject_token_type: "access_token", - token_url: `${REPLIT_SIDECAR_ENDPOINT}/token`, - type: "external_account", - credential_source: { - url: `${REPLIT_SIDECAR_ENDPOINT}/credential`, - format: { - type: "json", - subject_token_field_name: "access_token", - }, - }, - universe_domain: "googleapis.com", - }, - projectId: "", -}); - -export class ObjectNotFoundError extends Error { - constructor() { - super("Object not found"); - this.name = "ObjectNotFoundError"; - Object.setPrototypeOf(this, ObjectNotFoundError.prototype); - } -} - -// The object storage service is used to interact with the object storage service. -export class ObjectStorageService { - constructor() {} - - // Gets the public object search paths. - getPublicObjectSearchPaths(): Array { - const pathsStr = process.env.PUBLIC_OBJECT_SEARCH_PATHS || ""; - const paths = Array.from( - new Set( - pathsStr - .split(",") - .map((path) => path.trim()) - .filter((path) => path.length > 0) - ) - ); - if (paths.length === 0) { - throw new Error( - "PUBLIC_OBJECT_SEARCH_PATHS not set. Create a bucket in 'Object Storage' " + - "tool and set PUBLIC_OBJECT_SEARCH_PATHS env var (comma-separated paths)." - ); - } - return paths; - } - - // Gets the private object directory. - getPrivateObjectDir(): string { - const dir = process.env.PRIVATE_OBJECT_DIR || ""; - if (!dir) { - throw new Error( - "PRIVATE_OBJECT_DIR not set. Create a bucket in 'Object Storage' " + - "tool and set PRIVATE_OBJECT_DIR env var." - ); - } - return dir; - } - - // Search for a public object from the search paths. - async searchPublicObject(filePath: string): Promise { - for (const searchPath of this.getPublicObjectSearchPaths()) { - const fullPath = `${searchPath}/${filePath}`; - - // Full path format: // - const { bucketName, objectName } = parseObjectPath(fullPath); - const bucket = objectStorageClient.bucket(bucketName); - const file = bucket.file(objectName); - - // Check if file exists - const [exists] = await file.exists(); - if (exists) { - return file; - } - } - - return null; - } - - // Downloads an object to the response. - async downloadObject(file: File, res: Response, cacheTtlSec: number = 3600) { - try { - // Get file metadata - const [metadata] = await file.getMetadata(); - // Get the ACL policy for the object. - const aclPolicy = await getObjectAclPolicy(file); - const isPublic = aclPolicy?.visibility === "public"; - // Set appropriate headers - res.set({ - "Content-Type": metadata.contentType || "application/octet-stream", - "Content-Length": metadata.size, - "Cache-Control": `${ - isPublic ? "public" : "private" - }, max-age=${cacheTtlSec}`, - }); - - // Stream the file to the response - const stream = file.createReadStream(); - - stream.on("error", (err) => { - console.error("Stream error:", err); - if (!res.headersSent) { - res.status(500).json({ error: "Error streaming file" }); - } - }); - - stream.pipe(res); - } catch (error) { - console.error("Error downloading file:", error); - if (!res.headersSent) { - res.status(500).json({ error: "Error downloading file" }); - } - } - } - - // Gets the upload URL for an object entity. - async getObjectEntityUploadURL(): Promise { - const privateObjectDir = this.getPrivateObjectDir(); - if (!privateObjectDir) { - throw new Error( - "PRIVATE_OBJECT_DIR not set. Create a bucket in 'Object Storage' " + - "tool and set PRIVATE_OBJECT_DIR env var." - ); - } - - const objectId = randomUUID(); - const fullPath = `${privateObjectDir}/uploads/${objectId}`; - - const { bucketName, objectName } = parseObjectPath(fullPath); - - // Sign URL for PUT method with TTL - return signObjectURL({ - bucketName, - objectName, - method: "PUT", - ttlSec: 900, - }); - } - - // Gets the object entity file from the object path. - async getObjectEntityFile(objectPath: string): Promise { - if (!objectPath.startsWith("/objects/")) { - throw new ObjectNotFoundError(); - } - - const parts = objectPath.slice(1).split("/"); - if (parts.length < 2) { - throw new ObjectNotFoundError(); - } - - const entityId = parts.slice(1).join("/"); - let entityDir = this.getPrivateObjectDir(); - if (!entityDir.endsWith("/")) { - entityDir = `${entityDir}/`; - } - const objectEntityPath = `${entityDir}${entityId}`; - const { bucketName, objectName } = parseObjectPath(objectEntityPath); - const bucket = objectStorageClient.bucket(bucketName); - const objectFile = bucket.file(objectName); - const [exists] = await objectFile.exists(); - if (!exists) { - throw new ObjectNotFoundError(); - } - return objectFile; - } - - normalizeObjectEntityPath( - rawPath: string, - ): string { - if (!rawPath.startsWith("https://storage.googleapis.com/")) { - return rawPath; - } - - // Extract the path from the URL by removing query parameters and domain - const url = new URL(rawPath); - const rawObjectPath = url.pathname; - - let objectEntityDir = this.getPrivateObjectDir(); - if (!objectEntityDir.endsWith("/")) { - objectEntityDir = `${objectEntityDir}/`; - } - - if (!rawObjectPath.startsWith(objectEntityDir)) { - return rawObjectPath; - } - - // Extract the entity ID from the path - const entityId = rawObjectPath.slice(objectEntityDir.length); - return `/objects/${entityId}`; - } - - // Tries to set the ACL policy for the object entity and return the normalized path. - async trySetObjectEntityAclPolicy( - rawPath: string, - aclPolicy: ObjectAclPolicy - ): Promise { - const normalizedPath = this.normalizeObjectEntityPath(rawPath); - if (!normalizedPath.startsWith("/")) { - return normalizedPath; - } - - const objectFile = await this.getObjectEntityFile(normalizedPath); - await setObjectAclPolicy(objectFile, aclPolicy); - return normalizedPath; - } - - // Checks if the user can access the object entity. - async canAccessObjectEntity({ - userId, - objectFile, - requestedPermission, - }: { - userId?: string; - objectFile: File; - requestedPermission?: ObjectPermission; - }): Promise { - return canAccessObject({ - userId, - objectFile, - requestedPermission: requestedPermission ?? ObjectPermission.READ, - }); - } -} - -function parseObjectPath(path: string): { - bucketName: string; - objectName: string; -} { - if (!path.startsWith("/")) { - path = `/${path}`; - } - const pathParts = path.split("/"); - if (pathParts.length < 3) { - throw new Error("Invalid path: must contain at least a bucket name"); - } - - const bucketName = pathParts[1]; - const objectName = pathParts.slice(2).join("/"); - - return { - bucketName, - objectName, - }; -} - -async function signObjectURL({ - bucketName, - objectName, - method, - ttlSec, -}: { - bucketName: string; - objectName: string; - method: "GET" | "PUT" | "DELETE" | "HEAD"; - ttlSec: number; -}): Promise { - const request = { - bucket_name: bucketName, - object_name: objectName, - method, - expires_at: new Date(Date.now() + ttlSec * 1000).toISOString(), - }; - const response = await fetch( - `${REPLIT_SIDECAR_ENDPOINT}/object-storage/signed-object-url`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(request), - } - ); - if (!response.ok) { - throw new Error( - `Failed to sign object URL, errorcode: ${response.status}, ` + - `make sure you're running on Replit` - ); - } - - const { signed_url: signedURL } = await response.json(); - return signedURL; -} diff --git a/server/openai.ts b/server/openai.ts deleted file mode 100644 index baf0dad..0000000 --- a/server/openai.ts +++ /dev/null @@ -1,194 +0,0 @@ -import OpenAI from "openai"; -import { File } from "@google-cloud/storage"; - -const openai = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY_ENV_VAR || "default_key" -}); - -// Analyze asset documents using AI vision -export async function analyzeAssetDocument( - file: File, - documentType: string, - mimeType: string | undefined -): Promise<{ aiAnalysis: any; extractedData: any } | null> { - try { - if (!mimeType?.startsWith('image/')) { - console.log("Skipping AI analysis - not an image file"); - return null; - } - - // Get the file as base64 - const [fileBuffer] = await file.download(); - const base64Image = fileBuffer.toString('base64'); - - // Use GPT-4o for document analysis - // the newest OpenAI model is "gpt-4o" which was released May 13, 2024. do not change this unless explicitly requested by the user - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are an expert asset documentation analyst. Analyze the provided ${documentType} image and extract relevant information. Return structured JSON data with extracted details and analysis insights.` - }, - { - role: "user", - content: [ - { - type: "text", - text: `Analyze this ${documentType} document and extract all relevant information including: dates, amounts, vendor information, product details, warranty information, serial numbers, model numbers, and any other important asset-related data. Provide both extracted structured data and analytical insights.` - }, - { - type: "image_url", - image_url: { - url: `data:${mimeType};base64,${base64Image}` - } - } - ], - }, - ], - response_format: { type: "json_object" }, - max_tokens: 1500, - }); - - const analysisResult = JSON.parse(response.choices[0].message.content || "{}"); - - return { - aiAnalysis: { - confidence: analysisResult.confidence || 0.8, - documentType: analysisResult.document_type || documentType, - extractionMethod: "openai-gpt4o-vision", - analysisDate: new Date().toISOString(), - insights: analysisResult.insights || [], - qualityScore: analysisResult.quality_score || 0.8 - }, - extractedData: { - vendor: analysisResult.vendor || null, - amount: analysisResult.amount || null, - date: analysisResult.date || null, - items: analysisResult.items || [], - serialNumber: analysisResult.serial_number || null, - model: analysisResult.model || null, - brand: analysisResult.brand || null, - category: analysisResult.category || null, - warranty: analysisResult.warranty || null, - additionalDetails: analysisResult.additional_details || {} - } - }; - } catch (error) { - console.error("Error analyzing document with OpenAI:", error); - return null; - } -} - -// Extract specific receipt data -export async function extractReceiptData(imageUrl: string): Promise { - try { - // the newest OpenAI model is "gpt-4o" which was released May 13, 2024. do not change this unless explicitly requested by the user - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: "You are a receipt analysis expert. Extract structured data from receipt images including merchant, date, total amount, tax, items, and payment method. Return valid JSON only." - }, - { - role: "user", - content: [ - { - type: "text", - text: "Extract all data from this receipt including: merchant name, date, total amount, tax amount, individual items with prices, payment method, and any other relevant details. Return as structured JSON." - }, - { - type: "image_url", - image_url: { url: imageUrl } - } - ], - }, - ], - response_format: { type: "json_object" }, - max_tokens: 1000, - }); - - return JSON.parse(response.choices[0].message.content || "{}"); - } catch (error) { - console.error("Error extracting receipt data:", error); - throw new Error("Failed to analyze receipt: " + (error as Error).message); - } -} - -// Generate legal document content -export async function generateLegalDocument( - templateType: string, - assetData: any, - ownerData: any -): Promise { - try { - // the newest OpenAI model is "gpt-4o" which was released May 13, 2024. do not change this unless explicitly requested by the user - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: `You are a legal document generation expert. Create a properly formatted ${templateType} document with official legal language, proper structure, and all necessary legal clauses.` - }, - { - role: "user", - content: `Generate a ${templateType} document for the following asset and owner information: - -Asset Details: -${JSON.stringify(assetData, null, 2)} - -Owner Details: -${JSON.stringify(ownerData, null, 2)} - -Include proper legal formatting, official language, signature blocks, notarization sections, and blockchain verification sections where appropriate.` - } - ], - max_tokens: 2000, - }); - - return response.choices[0].message.content || ""; - } catch (error) { - console.error("Error generating legal document:", error); - throw new Error("Failed to generate legal document: " + (error as Error).message); - } -} - -// Calculate trust score based on asset data -export async function calculateAssetTrustScore(assetData: any): Promise { - try { - // the newest OpenAI model is "gpt-4o" which was released May 13, 2024. do not change this unless explicitly requested by the user - const response = await openai.chat.completions.create({ - model: "gpt-4o", - messages: [ - { - role: "system", - content: "You are a trust scoring expert. Analyze asset data and calculate a trust score from 0.0 to 1.0 based on verification factors, document quality, blockchain verification, and data completeness. Return only a JSON object with the score and reasoning." - }, - { - role: "user", - content: `Calculate a trust score for this asset data: -${JSON.stringify(assetData, null, 2)} - -Consider factors like: -- Document completeness and quality -- Verification status -- Blockchain/immutable evidence -- Cross-reference consistency -- Time factors -- Source credibility - -Return JSON format: { "score": 0.85, "factors": [...], "reasoning": "..." }` - } - ], - response_format: { type: "json_object" }, - max_tokens: 500, - }); - - const result = JSON.parse(response.choices[0].message.content || '{"score": 0.5}'); - return Math.max(0, Math.min(1, result.score || 0.5)); - } catch (error) { - console.error("Error calculating trust score:", error); - return 0.5; // Default moderate trust score - } -} diff --git a/server/routes.ts b/server/routes.ts deleted file mode 100644 index 4baa4c6..0000000 --- a/server/routes.ts +++ /dev/null @@ -1,673 +0,0 @@ -import type { Express } from "express"; -import { createServer, type Server } from "http"; -import { storage } from "./storage"; -import { chittyAuth, requireChittyAuth, requireVerifiedChitty } from "./chittyAuth"; -import { setupGitHubWebhooks } from "./githubWebhooks"; -import { ObjectStorageService, ObjectNotFoundError } from "./objectStorage"; -import { ObjectPermission } from "./objectAcl"; -import { aiAnalysisService } from "./aiAnalysis"; -import { seedDemoData } from "./seedData"; -import { initializeChittyCore, getChittyServices, getEvidenceLedger } from "./chittyCore"; -import { insertAssetSchema, insertEvidenceSchema, insertTimelineEventSchema, - insertWarrantySchema, insertInsurancePolicySchema, insertLegalCaseSchema } from "@shared/schema"; -import { z } from "zod"; -import { listToolResources } from "./toolRegistry"; - -export async function registerRoutes(app: Express): Promise { - // Initialize ChittyCloudflare Core - await initializeChittyCore(); - - // ChittyAuth middleware - await chittyAuth.setupAuth(app); - - // GitHub App webhooks - setupGitHubWebhooks(app); - - // Auth routes - app.get('/api/auth/user', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const user = await storage.getUser(userId); - res.json(user); - } catch (error) { - console.error("Error fetching user:", error); - res.status(500).json({ message: "Failed to fetch user" }); - } - }); - - // Demo data route - app.post('/api/seed-demo', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const assetCount = await seedDemoData(userId); - res.json({ message: `Created ${assetCount} demo assets`, assetCount }); - } catch (error) { - console.error("Error seeding demo data:", error); - res.status(500).json({ message: "Failed to seed demo data" }); - } - }); - - // ChittyOS Evidence Ledger routes - app.post('/api/evidence-ledger/submit', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const evidenceLedger = await getEvidenceLedger(); - - const result = await evidenceLedger.submitEvidence({ - evidenceType: req.body.evidenceType, - data: req.body.data, - metadata: { - ...req.body.metadata, - submissionSource: 'ChittyAssets', - }, - submitterId: userId, - }); - - res.json({ - success: true, - chittyId: result.chittyId, - status: result.status, - trustScore: result.trustScore, - retentionUntil: result.retentionUntil, - chainResult: result.chainResult, - }); - } catch (error) { - console.error("Error submitting evidence:", error); - res.status(500).json({ message: "Failed to submit evidence to ledger" }); - } - }); - - app.get('/api/evidence-ledger/:chittyId', requireChittyAuth(), async (req: any, res) => { - try { - const evidenceLedger = await getEvidenceLedger(); - const evidence = await evidenceLedger.getEvidence(req.params.chittyId); - - res.json(evidence); - } catch (error) { - console.error("Error retrieving evidence:", error); - res.status(500).json({ message: "Failed to retrieve evidence" }); - } - }); - - app.post('/api/evidence-ledger/:chittyId/verify', requireChittyAuth(), async (req: any, res) => { - try { - const evidenceLedger = await getEvidenceLedger(); - const verification = await evidenceLedger.verifyEvidence(req.params.chittyId); - - res.json(verification); - } catch (error) { - console.error("Error verifying evidence:", error); - res.status(500).json({ message: "Failed to verify evidence" }); - } - }); - - // ChittyOS Ecosystem status - app.get('/api/ecosystem/status', requireChittyAuth(), async (req: any, res) => { - try { - const services = await getChittyServices(); - const status = await services.getEcosystemStatus(); - res.json(status); - } catch (error) { - console.error("Error fetching ecosystem status:", error); - res.status(500).json({ message: "Failed to fetch ecosystem status" }); - } - }); - - // API Tool Surface - expose all available connectors to the agent layer - app.get('/api/tools/resources', requireChittyAuth(), (_req: any, res) => { - const resources = listToolResources(); - res.json({ - resources, - callableResources: resources.filter(r => r.callable).map(r => r.id), - }); - }); - - app.post('/api/assets/:id/freeze', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const asset = await storage.getAsset(req.params.id, userId); - - if (!asset) { - return res.status(404).json({ message: "Asset not found" }); - } - - // Freeze asset on ChittyChain - const services = await getChittyServices(); - const freezeResult = await services.assets.freeze(asset.chittyId || asset.id); - - if (!freezeResult.success) { - return res.status(500).json({ message: freezeResult.error }); - } - - // Update asset with freeze data - const updatedAsset = await storage.updateAsset(req.params.id, userId, { - chittyChainStatus: 'frozen', - ipfsHash: freezeResult.ipfsHash, - freezeTimestamp: new Date(freezeResult.freezeTimestamp!), - }); - - // Create timeline event - await storage.createTimelineEvent({ - assetId: asset.id, - userId, - eventType: 'other', - title: 'Asset frozen on ChittyChain', - description: '7-day immutability period started', - eventDate: new Date(), - }); - - res.json(updatedAsset); - } catch (error) { - console.error("Error freezing asset:", error); - res.status(500).json({ message: "Failed to freeze asset" }); - } - }); - - app.post('/api/assets/:id/mint', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const asset = await storage.getAsset(req.params.id, userId); - - if (!asset) { - return res.status(404).json({ message: "Asset not found" }); - } - - if (asset.chittyChainStatus !== 'frozen') { - return res.status(400).json({ message: "Asset must be frozen before minting" }); - } - - // Mint evidence token - const services = await getChittyServices(); - const mintResult = await services.chain.mint( - asset.chittyId || asset.id, - { ipfsHash: asset.ipfsHash || 'placeholder' } - ); - - if (!mintResult.success) { - return res.status(500).json({ message: mintResult.error }); - } - - // Update asset with mint data - const updatedAsset = await storage.updateAsset(req.params.id, userId, { - chittyChainStatus: 'minted', - blockchainHash: mintResult.transactionHash, - mintingFee: '0.1', - }); - - // Create timeline event - await storage.createTimelineEvent({ - assetId: asset.id, - userId, - eventType: 'other', - title: 'Evidence token minted', - description: 'Asset ownership token created on ChittyChain', - eventDate: new Date(), - }); - - res.json(updatedAsset); - } catch (error) { - console.error("Error minting asset:", error); - res.status(500).json({ message: "Failed to mint asset" }); - } - }); - - // Asset routes - app.get('/api/assets', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const filters = { - assetType: req.query.type as string, - status: req.query.status as string, - searchTerm: req.query.search as string, - minValue: req.query.minValue ? parseFloat(req.query.minValue as string) : undefined, - maxValue: req.query.maxValue ? parseFloat(req.query.maxValue as string) : undefined, - }; - - const assets = await storage.getUserAssets(userId, filters); - res.json(assets); - } catch (error) { - console.error("Error fetching assets:", error); - res.status(500).json({ message: "Failed to fetch assets" }); - } - }); - - app.get('/api/assets/stats', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const stats = await storage.getAssetStats(userId); - res.json(stats); - } catch (error) { - console.error("Error fetching asset stats:", error); - res.status(500).json({ message: "Failed to fetch asset stats" }); - } - }); - - app.get('/api/assets/:id', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const asset = await storage.getAsset(req.params.id, userId); - if (!asset) { - return res.status(404).json({ message: "Asset not found" }); - } - res.json(asset); - } catch (error) { - console.error("Error fetching asset:", error); - res.status(500).json({ message: "Failed to fetch asset" }); - } - }); - - app.post('/api/assets', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - - // Generate ChittyChain identifier via Core - const services = await getChittyServices(); - const chittyIdResult = await services.id.generate('asset'); - const chittyId = chittyIdResult.chittyId || chittyIdResult.id; - - // Calculate trust score using ChittyTrust - const trustResult = await services.trust.calculate(chittyId, req.body); - - const assetData = insertAssetSchema.parse({ - ...req.body, - userId, - chittyId, - trustScore: trustResult.trustScore.toString(), - chittyChainStatus: 'draft', - metadata: { - ...req.body.metadata, - trustFactors: trustResult.factors, - trustConfidence: trustResult.confidence, - } - }); - - const asset = await storage.createAsset(assetData); - - // Create initial timeline event - await storage.createTimelineEvent({ - assetId: asset.id, - userId, - eventType: 'acquisition', - title: `Asset "${asset.name}" added to portfolio`, - description: 'Initial asset registration with ChittyChain integration', - eventDate: new Date(), - }); - - res.status(201).json(asset); - } catch (error) { - console.error("Error creating asset:", error); - if (error instanceof z.ZodError) { - return res.status(400).json({ message: "Invalid asset data", errors: error.errors }); - } - res.status(500).json({ message: "Failed to create asset" }); - } - }); - - app.put('/api/assets/:id', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const updates = req.body; - delete updates.id; - delete updates.userId; - delete updates.createdAt; - delete updates.updatedAt; - - const asset = await storage.updateAsset(req.params.id, userId, updates); - res.json(asset); - } catch (error) { - console.error("Error updating asset:", error); - res.status(500).json({ message: "Failed to update asset" }); - } - }); - - app.delete('/api/assets/:id', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - await storage.deleteAsset(req.params.id, userId); - res.status(204).send(); - } catch (error) { - console.error("Error deleting asset:", error); - res.status(500).json({ message: "Failed to delete asset" }); - } - }); - - // Evidence routes - app.get('/api/assets/:assetId/evidence', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const evidence = await storage.getAssetEvidence(req.params.assetId, userId); - res.json(evidence); - } catch (error) { - console.error("Error fetching evidence:", error); - res.status(500).json({ message: "Failed to fetch evidence" }); - } - }); - - app.post('/api/assets/:assetId/evidence', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const evidenceData = insertEvidenceSchema.parse({ - ...req.body, - assetId: req.params.assetId, - userId - }); - - const evidence = await storage.createEvidence(evidenceData); - - // Create timeline event - await storage.createTimelineEvent({ - assetId: req.params.assetId, - userId, - eventType: 'evidence_added', - title: `Evidence "${evidence.name}" added`, - description: `New ${evidence.evidenceType} evidence uploaded`, - eventDate: new Date(), - relatedEvidenceId: evidence.id, - }); - - res.status(201).json(evidence); - } catch (error) { - console.error("Error creating evidence:", error); - if (error instanceof z.ZodError) { - return res.status(400).json({ message: "Invalid evidence data", errors: error.errors }); - } - res.status(500).json({ message: "Failed to create evidence" }); - } - }); - - // AI Analysis routes - app.post('/api/evidence/:evidenceId/analyze', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const { base64Image, analysisType } = req.body; - - if (!base64Image || !analysisType) { - return res.status(400).json({ message: "Missing required fields" }); - } - - const evidenceItem = await storage.getEvidence(req.params.evidenceId, userId); - if (!evidenceItem) { - return res.status(404).json({ message: "Evidence not found" }); - } - - let results; - let confidence = 0; - const startTime = Date.now(); - - switch (analysisType) { - case 'receipt': - results = await aiAnalysisService.analyzeReceipt(base64Image); - confidence = results.confidence; - break; - case 'document': - results = await aiAnalysisService.analyzeDocument(base64Image); - confidence = results.confidence; - break; - case 'asset_valuation': - const asset = await storage.getAsset(evidenceItem.assetId, userId); - results = await aiAnalysisService.analyzeAssetPhoto(base64Image, asset?.assetType || 'unknown'); - confidence = results.confidence; - break; - default: - return res.status(400).json({ message: "Invalid analysis type" }); - } - - const processingTime = Date.now() - startTime; - - // Store analysis results - const analysisResult = await storage.createAiAnalysisResult({ - evidenceId: req.params.evidenceId, - analysisType, - confidence: confidence.toString(), - results, - processingTime, - modelUsed: 'gpt-4o', - }); - - // Update evidence with AI analysis - await storage.updateEvidence(req.params.evidenceId, userId, { - aiAnalysis: results, - verificationStatus: confidence > 0.8 ? 'verified' : 'pending' - }); - - res.json(analysisResult); - } catch (error) { - console.error("Error analyzing evidence:", error); - res.status(500).json({ message: "Failed to analyze evidence" }); - } - }); - - // Timeline routes - app.get('/api/assets/:assetId/timeline', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const timeline = await storage.getAssetTimeline(req.params.assetId, userId); - res.json(timeline); - } catch (error) { - console.error("Error fetching timeline:", error); - res.status(500).json({ message: "Failed to fetch timeline" }); - } - }); - - // Warranty routes - app.get('/api/assets/:assetId/warranties', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const warranties = await storage.getAssetWarranties(req.params.assetId, userId); - res.json(warranties); - } catch (error) { - console.error("Error fetching warranties:", error); - res.status(500).json({ message: "Failed to fetch warranties" }); - } - }); - - app.get('/api/warranties/expiring', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const daysAhead = parseInt(req.query.days as string) || 30; - const warranties = await storage.getExpiringWarranties(userId, daysAhead); - res.json(warranties); - } catch (error) { - console.error("Error fetching expiring warranties:", error); - res.status(500).json({ message: "Failed to fetch expiring warranties" }); - } - }); - - app.post('/api/assets/:assetId/warranties', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const warrantyData = insertWarrantySchema.parse({ - ...req.body, - assetId: req.params.assetId, - userId - }); - - const warranty = await storage.createWarranty(warrantyData); - res.status(201).json(warranty); - } catch (error) { - console.error("Error creating warranty:", error); - if (error instanceof z.ZodError) { - return res.status(400).json({ message: "Invalid warranty data", errors: error.errors }); - } - res.status(500).json({ message: "Failed to create warranty" }); - } - }); - - // Insurance routes - app.get('/api/assets/:assetId/insurance', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const insurance = await storage.getAssetInsurance(req.params.assetId, userId); - res.json(insurance); - } catch (error) { - console.error("Error fetching insurance:", error); - res.status(500).json({ message: "Failed to fetch insurance" }); - } - }); - - app.post('/api/assets/:assetId/insurance', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const insuranceData = insertInsurancePolicySchema.parse({ - ...req.body, - assetId: req.params.assetId, - userId - }); - - const insurance = await storage.createInsurancePolicy(insuranceData); - res.status(201).json(insurance); - } catch (error) { - console.error("Error creating insurance:", error); - if (error instanceof z.ZodError) { - return res.status(400).json({ message: "Invalid insurance data", errors: error.errors }); - } - res.status(500).json({ message: "Failed to create insurance" }); - } - }); - - // Legal case routes - app.get('/api/legal-cases', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const cases = await storage.getUserLegalCases(userId); - res.json(cases); - } catch (error) { - console.error("Error fetching legal cases:", error); - res.status(500).json({ message: "Failed to fetch legal cases" }); - } - }); - - app.post('/api/legal-cases', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const caseData = insertLegalCaseSchema.parse({ ...req.body, userId }); - - const legalCase = await storage.createLegalCase(caseData); - res.status(201).json(legalCase); - } catch (error) { - console.error("Error creating legal case:", error); - if (error instanceof z.ZodError) { - return res.status(400).json({ message: "Invalid case data", errors: error.errors }); - } - res.status(500).json({ message: "Failed to create legal case" }); - } - }); - - // Legal document generation - app.post('/api/legal/generate-document', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const { templateType, assetId, jurisdiction, includeNotarization, includeBlockchain } = req.body; - - if (!templateType || !assetId) { - return res.status(400).json({ message: "Missing required fields" }); - } - - const asset = await storage.getAsset(assetId, userId); - if (!asset) { - return res.status(404).json({ message: "Asset not found" }); - } - - const evidence = await storage.getAssetEvidence(assetId, userId); - const timeline = await storage.getAssetTimeline(assetId, userId); - - const documentData = { - asset, - evidence: evidence.slice(0, 5), // Include top 5 pieces of evidence - timeline: timeline.slice(0, 10), // Include recent timeline events - includeNotarization, - includeBlockchain, - }; - - const document = await aiAnalysisService.generateLegalDocument( - templateType, - documentData, - jurisdiction || 'New York State' - ); - - res.json({ document, templateType, jurisdiction }); - } catch (error) { - console.error("Error generating legal document:", error); - res.status(500).json({ message: "Failed to generate legal document" }); - } - }); - - // Trust score calculation - app.post('/api/assets/:assetId/calculate-trust-score', requireChittyAuth(), async (req: any, res) => { - try { - const userId = `chitty_${req.auth.userId}`; - const asset = await storage.getAsset(req.params.assetId, userId); - if (!asset) { - return res.status(404).json({ message: "Asset not found" }); - } - - const evidence = await storage.getAssetEvidence(req.params.assetId, userId); - const trustScore = await aiAnalysisService.calculateTrustScore(asset, evidence); - - // Update asset with new trust score - await storage.updateAsset(req.params.assetId, userId, { trustScore: trustScore.toString() }); - - res.json({ trustScore }); - } catch (error) { - console.error("Error calculating trust score:", error); - res.status(500).json({ message: "Failed to calculate trust score" }); - } - }); - - // Object storage routes for evidence files - app.get("/objects/:objectPath(*)", requireChittyAuth(), async (req: any, res) => { - const userId = req.auth ? `chitty_${req.auth.userId}` : undefined; - const objectStorageService = new ObjectStorageService(); - try { - const objectFile = await objectStorageService.getObjectEntityFile(req.path); - const canAccess = await objectStorageService.canAccessObjectEntity({ - objectFile, - userId: userId, - requestedPermission: ObjectPermission.READ, - }); - if (!canAccess) { - return res.sendStatus(401); - } - objectStorageService.downloadObject(objectFile, res); - } catch (error) { - console.error("Error checking object access:", error); - if (error instanceof ObjectNotFoundError) { - return res.sendStatus(404); - } - return res.sendStatus(500); - } - }); - - app.post("/api/objects/upload", requireChittyAuth(), async (req: any, res) => { - const objectStorageService = new ObjectStorageService(); - const uploadURL = await objectStorageService.getObjectEntityUploadURL(); - res.json({ uploadURL }); - }); - - app.put("/api/evidence-files", requireChittyAuth(), async (req: any, res) => { - if (!req.body.fileURL) { - return res.status(400).json({ error: "fileURL is required" }); - } - - const userId = req.auth ? `chitty_${req.auth.userId}` : undefined; - - try { - const objectStorageService = new ObjectStorageService(); - const objectPath = await objectStorageService.trySetObjectEntityAclPolicy( - req.body.fileURL, - { - owner: userId, - visibility: "private", // Evidence files should be private - }, - ); - - res.status(200).json({ objectPath }); - } catch (error) { - console.error("Error setting evidence file:", error); - res.status(500).json({ error: "Internal server error" }); - } - }); - - const httpServer = createServer(app); - return httpServer; -} diff --git a/server/seedData.ts b/server/seedData.ts deleted file mode 100644 index da3c59d..0000000 --- a/server/seedData.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { storage } from "./storage"; -import { chittyCloudMcp } from "./chittyCloudMcp"; - -export async function seedDemoData(userId: string) { - try { - // Create demo assets with ChittyChain integration - const demoAssets = [ - { - userId, - name: "MacBook Pro 16-inch", - description: "High-performance laptop for professional work with M3 Max chip", - assetType: "electronics" as const, - status: "active" as const, - purchasePrice: "3499.00", - currentValue: "2800.00", - purchaseDate: new Date("2024-01-15"), - location: "Home Office", - serialNumber: "MBP2024001", - model: "MacBook Pro 16-inch", - manufacturer: "Apple", - condition: "excellent", - trustScore: "92.5", - chittyId: await chittyCloudMcp.generateChittyId(), - verificationStatus: "verified" as const, - chittyChainStatus: "minted" as const, - tags: ["work", "computer", "apple", "high-value"], - metadata: { - warranty: "AppleCare+ until 2027", - specifications: { - processor: "M3 Max", - memory: "32GB", - storage: "1TB SSD" - } - } - }, - { - userId, - name: "2023 Tesla Model Y", - description: "Electric SUV with Full Self-Driving capability", - assetType: "vehicle" as const, - status: "active" as const, - purchasePrice: "68990.00", - currentValue: "58500.00", - purchaseDate: new Date("2023-06-20"), - location: "Garage", - serialNumber: "5YJYGDEE3NF123456", - model: "Model Y", - manufacturer: "Tesla", - condition: "excellent", - trustScore: "96.8", - chittyId: await chittyCloudMcp.generateChittyId(), - verificationStatus: "verified" as const, - chittyChainStatus: "settled" as const, - tags: ["vehicle", "electric", "tesla", "high-value"], - metadata: { - vin: "5YJYGDEE3NF123456", - features: ["Full Self-Driving", "Premium Interior", "Tow Package"], - color: "Pearl White Multi-Coat" - } - }, - { - userId, - name: "Rolex Submariner", - description: "Luxury diving watch with ceramic bezel", - assetType: "jewelry" as const, - status: "active" as const, - purchasePrice: "9550.00", - currentValue: "12500.00", - purchaseDate: new Date("2022-12-10"), - location: "Safe Deposit Box", - serialNumber: "11649325", - model: "Submariner Date", - manufacturer: "Rolex", - condition: "mint", - trustScore: "98.2", - chittyId: await chittyCloudMcp.generateChittyId(), - verificationStatus: "verified" as const, - chittyChainStatus: "settled" as const, - tags: ["luxury", "watch", "rolex", "investment"], - metadata: { - reference: "126610LV", - movement: "Caliber 3235", - authentication: "Certified by Rolex" - } - }, - { - userId, - name: "Original Picasso Sketch", - description: "Pencil sketch from Pablo Picasso's Blue Period", - assetType: "artwork" as const, - status: "active" as const, - purchasePrice: "45000.00", - currentValue: "78000.00", - purchaseDate: new Date("2020-08-15"), - location: "Climate-Controlled Storage", - serialNumber: "PP1904-BS", - model: "Blue Period Sketch", - manufacturer: "Pablo Picasso", - condition: "excellent", - trustScore: "94.7", - chittyId: await chittyCloudMcp.generateChittyId(), - verificationStatus: "verified" as const, - chittyChainStatus: "frozen" as const, - freezeTimestamp: new Date(), - tags: ["art", "picasso", "investment", "collectible"], - metadata: { - provenance: "Authenticated by Picasso Foundation", - dimensions: "12x16 inches", - medium: "Pencil on paper" - } - }, - { - userId, - name: "Home Office Property", - description: "Commercial property used as home office and studio", - assetType: "real_estate" as const, - status: "active" as const, - purchasePrice: "650000.00", - currentValue: "825000.00", - purchaseDate: new Date("2021-03-10"), - location: "123 Innovation Drive, Tech City", - serialNumber: "PROP-2021-001", - model: "Commercial Office Space", - manufacturer: "Custom Build", - condition: "excellent", - trustScore: "89.3", - chittyId: await chittyCloudMcp.generateChittyId(), - verificationStatus: "pending" as const, - chittyChainStatus: "draft" as const, - tags: ["real-estate", "commercial", "office", "investment"], - metadata: { - sqft: "2500", - zoning: "Commercial", - taxId: "123-456-789" - } - } - ]; - - // Create the assets - for (const assetData of demoAssets) { - await storage.createAsset(assetData); - } - - console.log(`Created ${demoAssets.length} demo assets for user ${userId}`); - return demoAssets.length; - } catch (error) { - console.error("Error seeding demo data:", error); - throw error; - } -} \ No newline at end of file diff --git a/server/storage.ts b/server/storage.ts deleted file mode 100644 index 5b85cf5..0000000 --- a/server/storage.ts +++ /dev/null @@ -1,371 +0,0 @@ -import { - users, - assets, - evidence, - timelineEvents, - warranties, - insurancePolicies, - legalCases, - aiAnalysisResults, - type User, - type UpsertUser, - type Asset, - type InsertAsset, - type Evidence, - type InsertEvidence, - type TimelineEvent, - type InsertTimelineEvent, - type Warranty, - type InsertWarranty, - type InsurancePolicy, - type InsertInsurancePolicy, - type LegalCase, - type InsertLegalCase, - type AiAnalysisResult, - type InsertAiAnalysisResult, -} from "@shared/schema"; -import { db } from "./db"; -import { eq, desc, and, gte, lte, ilike, sql } from "drizzle-orm"; - -export interface IStorage { - // User operations (required for Replit Auth) - getUser(id: string): Promise; - upsertUser(user: UpsertUser): Promise; - - // Asset operations - createAsset(asset: InsertAsset): Promise; - getAsset(id: string, userId: string): Promise; - getUserAssets(userId: string, filters?: AssetFilters): Promise; - updateAsset(id: string, userId: string, updates: Partial): Promise; - deleteAsset(id: string, userId: string): Promise; - getAssetStats(userId: string): Promise; - - // Evidence operations - createEvidence(evidence: InsertEvidence): Promise; - getEvidence(id: string, userId: string): Promise; - getAssetEvidence(assetId: string, userId: string): Promise; - updateEvidence(id: string, userId: string, updates: Partial): Promise; - deleteEvidence(id: string, userId: string): Promise; - - // Timeline operations - createTimelineEvent(event: InsertTimelineEvent): Promise; - getAssetTimeline(assetId: string, userId: string): Promise; - - // Warranty operations - createWarranty(warranty: InsertWarranty): Promise; - getAssetWarranties(assetId: string, userId: string): Promise; - getExpiringWarranties(userId: string, daysAhead: number): Promise; - updateWarranty(id: string, userId: string, updates: Partial): Promise; - - // Insurance operations - createInsurancePolicy(policy: InsertInsurancePolicy): Promise; - getAssetInsurance(assetId: string, userId: string): Promise; - getActiveInsurance(userId: string): Promise; - - // Legal case operations - createLegalCase(legalCase: InsertLegalCase): Promise; - getUserLegalCases(userId: string): Promise; - updateLegalCase(id: string, userId: string, updates: Partial): Promise; - - // AI analysis operations - createAiAnalysisResult(result: InsertAiAnalysisResult): Promise; - getEvidenceAnalysis(evidenceId: string): Promise; -} - -export interface AssetFilters { - assetType?: string; - status?: string; - searchTerm?: string; - minValue?: number; - maxValue?: number; - createdAfter?: Date; - createdBefore?: Date; -} - -export interface AssetStats { - totalAssets: number; - totalValue: number; - verifiedAssets: number; - averageTrustScore: number; - assetsByType: Record; - assetsByStatus: Record; -} - -export class DatabaseStorage implements IStorage { - // User operations - async getUser(id: string): Promise { - const [user] = await db.select().from(users).where(eq(users.id, id)); - return user; - } - - async upsertUser(userData: UpsertUser): Promise { - const [user] = await db - .insert(users) - .values(userData) - .onConflictDoUpdate({ - target: users.id, - set: { - ...userData, - updatedAt: new Date(), - }, - }) - .returning(); - return user; - } - - // Asset operations - async createAsset(asset: InsertAsset): Promise { - const [newAsset] = await db.insert(assets).values(asset).returning(); - return newAsset; - } - - async getAsset(id: string, userId: string): Promise { - const [asset] = await db - .select() - .from(assets) - .where(and(eq(assets.id, id), eq(assets.userId, userId))); - return asset; - } - - async getUserAssets(userId: string, filters?: AssetFilters): Promise { - let query = db.select().from(assets).where(eq(assets.userId, userId)); - - if (filters) { - const conditions = [eq(assets.userId, userId)]; - - if (filters.assetType) { - conditions.push(eq(assets.assetType, filters.assetType as any)); - } - - if (filters.status) { - conditions.push(eq(assets.status, filters.status as any)); - } - - if (filters.searchTerm) { - conditions.push( - sql`${assets.name} ILIKE ${`%${filters.searchTerm}%`} OR ${assets.description} ILIKE ${`%${filters.searchTerm}%`}` - ); - } - - if (filters.minValue) { - conditions.push(gte(assets.currentValue, filters.minValue.toString())); - } - - if (filters.maxValue) { - conditions.push(lte(assets.currentValue, filters.maxValue.toString())); - } - - if (filters.createdAfter) { - conditions.push(gte(assets.createdAt, filters.createdAfter)); - } - - if (filters.createdBefore) { - conditions.push(lte(assets.createdAt, filters.createdBefore)); - } - - query = db.select().from(assets).where(and(...conditions)); - } - - return query.orderBy(desc(assets.createdAt)); - } - - async updateAsset(id: string, userId: string, updates: Partial): Promise { - const [updatedAsset] = await db - .update(assets) - .set({ ...updates, updatedAt: new Date() }) - .where(and(eq(assets.id, id), eq(assets.userId, userId))) - .returning(); - return updatedAsset; - } - - async deleteAsset(id: string, userId: string): Promise { - await db.delete(assets).where(and(eq(assets.id, id), eq(assets.userId, userId))); - } - - async getAssetStats(userId: string): Promise { - const userAssets = await db.select().from(assets).where(eq(assets.userId, userId)); - - const totalAssets = userAssets.length; - const totalValue = userAssets.reduce((sum, asset) => - sum + (asset.currentValue ? parseFloat(asset.currentValue) : 0), 0 - ); - const verifiedAssets = userAssets.filter(asset => asset.verificationStatus === 'verified').length; - const averageTrustScore = userAssets.reduce((sum, asset) => - sum + (asset.trustScore ? parseFloat(asset.trustScore) : 0), 0 - ) / (totalAssets || 1); - - const assetsByType: Record = {}; - const assetsByStatus: Record = {}; - - userAssets.forEach(asset => { - assetsByType[asset.assetType] = (assetsByType[asset.assetType] || 0) + 1; - assetsByStatus[asset.status || 'unknown'] = (assetsByStatus[asset.status || 'unknown'] || 0) + 1; - }); - - return { - totalAssets, - totalValue, - verifiedAssets, - averageTrustScore, - assetsByType, - assetsByStatus, - }; - } - - // Evidence operations - async createEvidence(evidenceData: InsertEvidence): Promise { - const [newEvidence] = await db.insert(evidence).values(evidenceData).returning(); - return newEvidence; - } - - async getEvidence(id: string, userId: string): Promise { - const [evidenceItem] = await db - .select() - .from(evidence) - .where(and(eq(evidence.id, id), eq(evidence.userId, userId))); - return evidenceItem; - } - - async getAssetEvidence(assetId: string, userId: string): Promise { - return db - .select() - .from(evidence) - .where(and(eq(evidence.assetId, assetId), eq(evidence.userId, userId))) - .orderBy(desc(evidence.createdAt)); - } - - async updateEvidence(id: string, userId: string, updates: Partial): Promise { - const [updatedEvidence] = await db - .update(evidence) - .set({ ...updates, updatedAt: new Date() }) - .where(and(eq(evidence.id, id), eq(evidence.userId, userId))) - .returning(); - return updatedEvidence; - } - - async deleteEvidence(id: string, userId: string): Promise { - await db.delete(evidence).where(and(eq(evidence.id, id), eq(evidence.userId, userId))); - } - - // Timeline operations - async createTimelineEvent(event: InsertTimelineEvent): Promise { - const [newEvent] = await db.insert(timelineEvents).values(event).returning(); - return newEvent; - } - - async getAssetTimeline(assetId: string, userId: string): Promise { - return db - .select() - .from(timelineEvents) - .where(and(eq(timelineEvents.assetId, assetId), eq(timelineEvents.userId, userId))) - .orderBy(desc(timelineEvents.eventDate)); - } - - // Warranty operations - async createWarranty(warranty: InsertWarranty): Promise { - const [newWarranty] = await db.insert(warranties).values(warranty).returning(); - return newWarranty; - } - - async getAssetWarranties(assetId: string, userId: string): Promise { - return db - .select() - .from(warranties) - .where(and(eq(warranties.assetId, assetId), eq(warranties.userId, userId))) - .orderBy(desc(warranties.endDate)); - } - - async getExpiringWarranties(userId: string, daysAhead: number): Promise { - const futureDate = new Date(); - futureDate.setDate(futureDate.getDate() + daysAhead); - - return db - .select() - .from(warranties) - .where( - and( - eq(warranties.userId, userId), - eq(warranties.isActive, true), - lte(warranties.endDate, futureDate), - gte(warranties.endDate, new Date()) - ) - ) - .orderBy(warranties.endDate); - } - - async updateWarranty(id: string, userId: string, updates: Partial): Promise { - const [updatedWarranty] = await db - .update(warranties) - .set({ ...updates, updatedAt: new Date() }) - .where(and(eq(warranties.id, id), eq(warranties.userId, userId))) - .returning(); - return updatedWarranty; - } - - // Insurance operations - async createInsurancePolicy(policy: InsertInsurancePolicy): Promise { - const [newPolicy] = await db.insert(insurancePolicies).values(policy).returning(); - return newPolicy; - } - - async getAssetInsurance(assetId: string, userId: string): Promise { - return db - .select() - .from(insurancePolicies) - .where(and(eq(insurancePolicies.assetId, assetId), eq(insurancePolicies.userId, userId))) - .orderBy(desc(insurancePolicies.endDate)); - } - - async getActiveInsurance(userId: string): Promise { - return db - .select() - .from(insurancePolicies) - .where( - and( - eq(insurancePolicies.userId, userId), - eq(insurancePolicies.isActive, true), - gte(insurancePolicies.endDate, new Date()) - ) - ) - .orderBy(insurancePolicies.endDate); - } - - // Legal case operations - async createLegalCase(legalCase: InsertLegalCase): Promise { - const [newCase] = await db.insert(legalCases).values(legalCase).returning(); - return newCase; - } - - async getUserLegalCases(userId: string): Promise { - return db - .select() - .from(legalCases) - .where(eq(legalCases.userId, userId)) - .orderBy(desc(legalCases.createdAt)); - } - - async updateLegalCase(id: string, userId: string, updates: Partial): Promise { - const [updatedCase] = await db - .update(legalCases) - .set({ ...updates, updatedAt: new Date() }) - .where(and(eq(legalCases.id, id), eq(legalCases.userId, userId))) - .returning(); - return updatedCase; - } - - // AI analysis operations - async createAiAnalysisResult(result: InsertAiAnalysisResult): Promise { - const [newResult] = await db.insert(aiAnalysisResults).values(result).returning(); - return newResult; - } - - async getEvidenceAnalysis(evidenceId: string): Promise { - return db - .select() - .from(aiAnalysisResults) - .where(eq(aiAnalysisResults.evidenceId, evidenceId)) - .orderBy(desc(aiAnalysisResults.createdAt)); - } -} - -export const storage = new DatabaseStorage(); diff --git a/server/toolRegistry.ts b/server/toolRegistry.ts deleted file mode 100644 index bfe1305..0000000 --- a/server/toolRegistry.ts +++ /dev/null @@ -1,67 +0,0 @@ -export type ToolCategory = - | 'cloudflare' - | 'content' - | 'communications' - | 'database'; - -export interface ToolResource { - id: string; - name: string; - provider: string; - description: string; - category: ToolCategory; - callable: boolean; - capabilities: string[]; -} - -const toolResources: ToolResource[] = [ - { - id: 'cloudflare.workers.assets', - name: 'Cloudflare Workers Evidence Tools', - provider: 'Cloudflare', - description: 'Edge Workers used by the Evidence Ledger for freeze/mint workflows.', - category: 'cloudflare', - callable: true, - capabilities: ['freeze', 'mint', 'status'], - }, - { - id: 'notion.search', - name: 'Notion Workspace Search', - provider: 'Notion', - description: 'Search across workspace pages, databases, and synced asset briefs.', - category: 'content', - callable: true, - capabilities: ['search', 'filter', 'page-context'], - }, - { - id: 'google.drive.search', - name: 'Google Drive Discovery', - provider: 'Google Drive', - description: 'Search Drive documents, spreadsheets, and evidence attachments.', - category: 'content', - callable: true, - capabilities: ['search', 'metadata', 'shared-drives'], - }, - { - id: 'outlook.mail.search', - name: 'Outlook / SharePoint Email + Files', - provider: 'Microsoft 365', - description: 'Search Outlook mailboxes and SharePoint file evidence for discovery.', - category: 'communications', - callable: true, - capabilities: ['search', 'attachments', 'sharepoint-sites'], - }, - { - id: 'neon.metadata.search', - name: 'Neon DB Metadata', - provider: 'Neon', - description: 'Search database schemas and column lineage for stored evidence.', - category: 'database', - callable: true, - capabilities: ['tables', 'columns', 'lineage'], - }, -]; - -export function listToolResources(): ToolResource[] { - return toolResources; -} diff --git a/server/vite.ts b/server/vite.ts deleted file mode 100644 index 9338c14..0000000 --- a/server/vite.ts +++ /dev/null @@ -1,85 +0,0 @@ -import express, { type Express } from "express"; -import fs from "fs"; -import path from "path"; -import { createServer as createViteServer, createLogger } from "vite"; -import { type Server } from "http"; -import viteConfig from "../vite.config"; -import { nanoid } from "nanoid"; - -const viteLogger = createLogger(); - -export function log(message: string, source = "express") { - const formattedTime = new Date().toLocaleTimeString("en-US", { - hour: "numeric", - minute: "2-digit", - second: "2-digit", - hour12: true, - }); - - console.log(`${formattedTime} [${source}] ${message}`); -} - -export async function setupVite(app: Express, server: Server) { - const serverOptions = { - middlewareMode: true, - hmr: { server }, - allowedHosts: true as const, - }; - - const vite = await createViteServer({ - ...viteConfig, - configFile: false, - customLogger: { - ...viteLogger, - error: (msg, options) => { - viteLogger.error(msg, options); - process.exit(1); - }, - }, - server: serverOptions, - appType: "custom", - }); - - app.use(vite.middlewares); - app.use("*", async (req, res, next) => { - const url = req.originalUrl; - - try { - const clientTemplate = path.resolve( - import.meta.dirname, - "..", - "client", - "index.html", - ); - - // always reload the index.html file from disk incase it changes - let template = await fs.promises.readFile(clientTemplate, "utf-8"); - template = template.replace( - `src="/src/main.tsx"`, - `src="/src/main.tsx?v=${nanoid()}"`, - ); - const page = await vite.transformIndexHtml(url, template); - res.status(200).set({ "Content-Type": "text/html" }).end(page); - } catch (e) { - vite.ssrFixStacktrace(e as Error); - next(e); - } - }); -} - -export function serveStatic(app: Express) { - const distPath = path.resolve(import.meta.dirname, "public"); - - if (!fs.existsSync(distPath)) { - throw new Error( - `Could not find the build directory: ${distPath}, make sure to build the client first`, - ); - } - - app.use(express.static(distPath)); - - // fall through to index.html if the file doesn't exist - app.use("*", (_req, res) => { - res.sendFile(path.resolve(distPath, "index.html")); - }); -} diff --git a/tsconfig.json b/tsconfig.json index 893b79c..c04b603 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["client/src/**/*", "shared/**/*", "server/**/*", "worker/src/**/*"], + "include": ["client/src/**/*", "shared/**/*", "worker/src/**/*"], "exclude": ["node_modules", "build", "dist", "**/*.test.ts"], "compilerOptions": { "incremental": true, diff --git a/vite.config.ts b/vite.config.ts index b383288..89ca4a2 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,9 +19,16 @@ export default defineConfig({ emptyOutDir: true, }, server: { + port: 5173, fs: { strict: true, deny: ["**/.*"], }, + proxy: { + "/api": { + target: "http://localhost:8788", + changeOrigin: true, + }, + }, }, });