diff --git a/package-lock.json b/package-lock.json index 12482a9e11..6ea3b1242f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -695,6 +695,18 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", + "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@google-cloud/local-auth": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@google-cloud/local-auth/-/local-auth-3.0.1.tgz", @@ -923,6 +935,65 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/@redis/bloom": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", + "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/client": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz", + "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "1.1.2", + "generic-pool": "3.9.0", + "yallist": "4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@redis/graph": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", + "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/json": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", + "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/search": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", + "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, + "node_modules/@redis/time-series": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", + "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" + } + }, "node_modules/@smithy/abort-controller": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.8.tgz", @@ -1559,6 +1630,13 @@ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -1591,6 +1669,16 @@ "form-data": "^4.0.0" } }, + "node_modules/@types/papaparse": { + "version": "5.3.15", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.15.tgz", + "integrity": "sha512-JHe6vF6x/8Z85nCX4yFdDslN11d+1pr12E526X8WAfhadOeaOTx5AuIkvDKIBopfvlzpzkdMx4YyvSKCM9oqtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/pg": { "version": "8.11.10", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz", @@ -1614,6 +1702,15 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "node_modules/@types/redis": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.10.tgz", + "integrity": "sha512-7CLy5b5fzzEGVcOccgZjoMlNpPhX6d10jEeRy2YWbFuaMNrSPc9ExRsMYsd+0VxvEHucf4EWx24Ja7cSU1FGUA==", + "license": "MIT", + "dependencies": { + "redis": "*" + } + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -1671,6 +1768,15 @@ "node": ">= 0.6" } }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -2011,6 +2117,19 @@ "node": ">=6" } }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chalk": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", @@ -2048,6 +2167,24 @@ "node": ">=12" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2076,6 +2213,19 @@ "node": ">= 0.8" } }, + "node_modules/complex.js": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.4.2.tgz", + "integrity": "sha512-qtx7HRhPGSCBtGiST4/WGHuW+zeaND/6Ld+db6PbrulIB1i2Ev/2UPiqcmpQNPSyfBKraC0EOvOKCB5dGZKt3g==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2139,6 +2289,18 @@ } } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2169,6 +2331,12 @@ "ms": "2.0.0" } }, + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "license": "MIT" + }, "node_modules/default-browser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", @@ -2379,6 +2547,12 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, + "node_modules/escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==", + "license": "MIT" + }, "node_modules/escodegen": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", @@ -2730,6 +2904,28 @@ "node": ">= 0.6" } }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/fraction.js": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.4.tgz", + "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -2792,6 +2988,15 @@ "node": ">=14" } }, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3299,6 +3504,12 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3381,6 +3592,29 @@ "node": ">=12" } }, + "node_modules/mathjs": { + "version": "12.4.3", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.4.3.tgz", + "integrity": "sha512-oHdGPDbp7gO873xxG90RLq36IuicuKvbpr/bBG5g9c8Obm/VsKVrK9uoRZZHUodohzlnmCEqfDzbR3LH6m+aAQ==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.24.4", + "complex.js": "^2.1.1", + "decimal.js": "^10.4.3", + "escape-latex": "^1.2.0", + "fraction.js": "4.3.4", + "javascript-natural-sort": "^0.7.1", + "seedrandom": "^3.0.5", + "tiny-emitter": "^2.1.0", + "typed-function": "^4.1.1" + }, + "bin": { + "mathjs": "bin/cli.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -3692,6 +3926,12 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, + "node_modules/papaparse": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.2.tgz", + "integrity": "sha512-PZXg8UuAc4PcVwLosEEDYjPyfWnTEhOrUfdv+3Bx+NuAb+5NhDmXzg5fHWmdCh1mP5p7JAZfFr3IMQfcntNAdA==", + "license": "MIT" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4172,6 +4412,16 @@ "node": ">= 0.10" } }, + "node_modules/redis": { + "resolved": "src/redis", + "link": true + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4330,6 +4580,12 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", + "license": "MIT" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -4578,6 +4834,18 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -4712,6 +4980,12 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "license": "MIT" + }, "node_modules/titleize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", @@ -4753,16 +5027,26 @@ "node": ">= 0.6" } }, + "node_modules/typed-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.2.1.tgz", + "integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, "node_modules/typed-query-selector": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==" }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", "devOptional": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4892,6 +5176,24 @@ "node": ">= 8" } }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -4951,6 +5253,27 @@ } } }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -4967,6 +5290,12 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -5178,7 +5507,11 @@ "@modelcontextprotocol/sdk": "0.5.0", "diff": "^5.1.0", "glob": "^10.3.10", + "lodash": "^4.17.21", + "mathjs": "^12.3.0", "minimatch": "^10.0.1", + "papaparse": "^5.4.1", + "xlsx": "^0.18.5", "zod-to-json-schema": "^3.23.5" }, "bin": { @@ -5186,8 +5519,10 @@ }, "devDependencies": { "@types/diff": "^5.0.9", + "@types/lodash": "^4.14.200", "@types/minimatch": "^5.1.2", "@types/node": "^22", + "@types/papaparse": "^5.3.14", "shx": "^0.3.4", "typescript": "^5.3.3" } @@ -5529,6 +5864,50 @@ "zod": "^3.23.8" } }, + "src/redis": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@modelcontextprotocol/sdk": "^0.4.0", + "@types/redis": "^4.0.10", + "redis": "^4.7.0" + }, + "bin": { + "redis": "build/index.js" + }, + "devDependencies": { + "@types/node": "^22.10.2", + "typescript": "^5.7.2" + } + }, + "src/redis/node_modules/@modelcontextprotocol/sdk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-0.4.0.tgz", + "integrity": "sha512-79gx8xh4o9YzdbtqMukOe5WKzvEZpvBA1x8PAgJWL7J5k06+vJx8NK2kWzOazPgqnfDego7cNEO8tjai/nOPAA==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "raw-body": "^3.0.0", + "zod": "^3.23.8" + } + }, + "src/redis/node_modules/redis": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", + "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==", + "license": "MIT", + "workspaces": [ + "./packages/*" + ], + "dependencies": { + "@redis/bloom": "1.2.0", + "@redis/client": "1.6.0", + "@redis/graph": "1.1.1", + "@redis/json": "1.0.7", + "@redis/search": "1.2.0", + "@redis/time-series": "1.1.0" + } + }, "src/sequentialthinking": { "name": "@modelcontextprotocol/server-sequential-thinking", "version": "0.6.2", diff --git a/src/filesystem/README.md b/src/filesystem/README.md index c52f1a4041..5b12af55b1 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -103,6 +103,149 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio - Returns: - Directories that this server can read/write from +- **execute_js_code** + - Execute JavaScript code on a specified file or directory + - Inputs: + - `code` (string): JavaScript code to execute + - `path` (string): File or directory path to operate on + - Features: + - Access to powerful libraries and Node.js standard modules: + - `fs` (fs/promises): File system operations + - `path`: Path utilities + - `readFileSync`: Direct file reading + - `_`: Lodash library + - `math`: MathJS library + - `Papa`: PapaParse library for CSV processing (if available) + - `XLSX`: SheetJS library for Excel files (if available) + - Support for both synchronous and asynchronous code (async/await) + - Console output capture (log, error, warn) + - Structured results via the `results` object + - `catchAsync()` helper function for handling errors in asynchronous code + - Context variables: + - `targetPath`: The validated absolute path + - `isDirectory`: Boolean indicating if path is a directory + - `isFile`: Boolean indicating if path is a file + - `fs`: Node.js fs/promises module + - `readFileSync`: Synchronous file reading function + - `_`: Lodash library + - `math`: MathJS library + - `Papa`: PapaParse library (if available) + - `XLSX`: SheetJS library (if available) + - `Buffer`, `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval` + - `catchAsync`: Helper function for safely handling async errors + - Returns: + - Console output from executed code + - Results object containing any data stored during execution + - Execution metadata (path info, errors if any) + - Example: + ```javascript + // Process a CSV file and calculate statistics + executeJSCode(` + // Read the CSV file + const content = await fs.readFile(targetPath, 'utf8'); + + // Parse the CSV data + const parsed = Papa.parse(content, {header: true, dynamicTyping: true}); + + // Calculate statistics using lodash + const data = parsed.data; + + // Store results for return + results.rowCount = data.length; + results.columnNames = Object.keys(data[0]); + + // Calculate numeric column statistics + const numericColumns = {}; + + results.columnNames.forEach(col => { + if (typeof data[0][col] === 'number') { + numericColumns[col] = { + min: _.minBy(data, col)[col], + max: _.maxBy(data, col)[col], + avg: _.meanBy(data, row => row[col]), + sum: _.sumBy(data, row => row[col]) + }; + } + }); + + results.statistics = numericColumns; + + console.log(\`Processed ${data.length} rows\`); + `, 'data.csv'); + ``` + + ```javascript + // Process all JavaScript files in a directory + executeJSCode(` + // Get all files in directory + const files = await fs.readdir(targetPath); + + // Filter for JavaScript files + const jsFiles = files.filter(file => file.endsWith('.js')); + + // Process each file + const fileStats = await Promise.all(jsFiles.map(async (file) => { + const filePath = path.join(targetPath, file); + const content = await fs.readFile(filePath, 'utf8'); + + // Count lines and functions + const lines = content.split('\n'); + const functionCount = (content.match(/function\s+\w+\s*\(/g) || []).length; + const arrowFunctionCount = (content.match(/(const|let|var)\s+\w+\s*=\s*\(.*\)\s*=>/g) || []).length; + + return { + file, + lineCount: lines.length, + functionCount: functionCount + arrowFunctionCount, + size: (await fs.stat(filePath)).size, + lastModified: (await fs.stat(filePath)).mtime + }; + })); + + // Calculate total stats + results.totalFiles = fileStats.length; + results.totalLines = _.sumBy(fileStats, 'lineCount'); + results.totalFunctions = _.sumBy(fileStats, 'functionCount'); + results.largestFile = _.maxBy(fileStats, 'size'); + results.fileDetails = fileStats; + + console.log(`Analyzed ${fileStats.length} JavaScript files`); + `, 'src'); + ``` + + ```javascript + // Example with catchAsync helper for error handling + executeJSCode(` + // Synchronous code + console.log("Starting execution..."); + + // Async code with proper error handling + catchAsync(async () => { + // Simulated async operation that could fail + setTimeout(() => { + try { + // This would normally crash the VM + throw new Error("This error is safely caught!"); + } catch (e) { + console.error("Caught timeout error:", e.message); + } + }, 100); + + // Process a file asynchronously + try { + const content = await fs.readFile(targetPath, 'utf8'); + results.fileRead = true; + results.fileSize = content.length; + } catch (err) { + console.error("File read error:", err.message); + results.fileRead = false; + } + }); + + console.log("Execution will continue even if async code fails"); + `, '/some/file/path'); + ``` + ## Usage with Claude Desktop Add this to your `claude_desktop_config.json`: diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index b4d5c419fc..5a7bd56919 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -8,8 +8,16 @@ import { ToolSchema, } from "@modelcontextprotocol/sdk/types.js"; import fs from "fs/promises"; +import { readFileSync } from "fs"; import path from "path"; import os from 'os'; +import vm from "vm"; +// Import libraries that will be used in executeJSCode +import lodashImport from "lodash"; +const _ = (lodashImport.defaults || lodashImport) as any; +import * as mathjs from "mathjs"; +import * as PapaParse from 'papaparse'; +import * as XLSX from 'xlsx'; import { z } from "zod"; import { zodToJsonSchema } from "zod-to-json-schema"; import { diffLines, createTwoFilesPatch } from 'diff'; @@ -146,6 +154,11 @@ const GetFileInfoArgsSchema = z.object({ path: z.string(), }); +const ExecuteJSCodeArgsSchema = z.object({ + code: z.string().describe('JavaScript code to execute'), + path: z.string().describe('File or directory path to operate on'), +}); + const ToolInputSchema = ToolSchema.shape.inputSchema; type ToolInput = z.infer; @@ -173,6 +186,99 @@ const server = new Server( ); // Tool implementations +async function executeJSCode(code: string, targetPath: string): Promise { + try { + // Validate the path + const validPath = await validatePath(targetPath); + const stats = await fs.stat(validPath); + + // Capture console.log output + const logs: string[] = []; + + // Create a console logger for the VM context + const consoleLogger = { + log: (...args: any[]) => { + logs.push(args.map(arg => + typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg) + ).join(' ')); + }, + error: (...args: any[]) => { + logs.push(`ERROR: ${args.map(arg => + typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg) + ).join(' ')}`); + }, + warn: (...args: any[]) => { + logs.push(`WARNING: ${args.map(arg => + typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg) + ).join(' ')}`); + } + } as Console; + + // Create context with libraries and utilities + const context: Record = { + fs, // fs/promises + readFileSync, // sync file reading + path, // path utilities + _, // lodash + math: mathjs, // Math operations + Papa: PapaParse, // CSV parsing + XLSX, // Excel file handling + Buffer, // Buffer handling + setTimeout, // Timers + clearTimeout, + setInterval, + clearInterval, + targetPath: validPath, // The validated path + isDirectory: stats.isDirectory(), + isFile: stats.isFile(), + // Store results to return + results: {}, + // Console for logging + console: consoleLogger + }; + + // Create VM context + const vmContext = vm.createContext(context); + + // A simpler approach - just run the code in an async function with proper error handling + const wrappedCode = ` + (async function() { + try { + ${code} + } catch (error) { + console.error('Error in executed code:', error instanceof Error ? error.message : String(error)); + if (error instanceof Error && error.stack) { + console.error('Stack trace:', error.stack); + } + } + })(); + `; + + // Run the script in the VM context + const script = new vm.Script(wrappedCode); + script.runInContext(vmContext); + + // For async operations, we need to wait a bit for them to complete + // This is a simple approach - add a small delay to let timeouts complete + await new Promise(resolve => setTimeout(resolve, 3000)); + + // Return results, logs, and metadata + return { + results: context.results, + logs, + isDirectory: context.isDirectory, + isFile: context.isFile, + targetPath: validPath + }; + } catch (error) { + return { + error: error instanceof Error ? error.message : String(error), + stack: error instanceof Error ? error.stack : undefined, + targetPath + }; + } +} + async function getFileStats(filePath: string): Promise { const stats = await fs.stat(filePath); return { @@ -435,6 +541,22 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { required: [], }, }, + { + name: "execute_js_code", + description: + "Execute JavaScript code on a specified file or directory, with access to powerful libraries. " + + "The code runs in a sandboxed VM in a Node.js environment with the following available: \n" + + "- Node.js standard libraries: fs (fs/promises), path, readFileSync, Buffer\n" + + "- Libraries: lodash (as _), mathjs (as math), papaparse (as Papa), xlsx (as XLSX)\n" + + "- Context variables: targetPath (validated path), isDirectory, isFile\n" + + "- Timers: setTimeout, clearTimeout, setInterval, clearInterval\n" + + "- Store results in the 'results' object to return them - THE CODE EXECUTION DOES NOT RETURN VALUES DIRECTLY\n" + + "- Use console.log(), console.warn(), and console.error() for output capture\n" + + "- Supports async/await when using 'await' keyword in your code\n" + + "- Code is automatically executed in an async context with error handling\n" + + "Only works within allowed directories.", + inputSchema: zodToJsonSchema(ExecuteJSCodeArgsSchema) as ToolInput, + }, ], }; }); @@ -620,6 +742,58 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }], }; } + + case "execute_js_code": { + try { + const parsed = ExecuteJSCodeArgsSchema.safeParse(args); + if (!parsed.success) { + throw new Error(`Invalid arguments for execute_js_code: ${parsed.error}`); + } + + const result = await executeJSCode(parsed.data.code, parsed.data.path); + + // Format the response + let responseText = ''; + + // Add any logs + if (result.logs && result.logs.length > 0) { + responseText += `== Console Output ==\n${result.logs.join('\n')}\n\n`; + } + + // Add results + responseText += `== Results ==\n${JSON.stringify(result.results, null, 2)}\n\n`; + + // Add metadata + responseText += `== Execution Info ==\n`; + responseText += `Path: ${result.targetPath}\n`; + responseText += `Type: ${result.isDirectory ? 'Directory' : 'File'}\n`; + + // Add any errors + if (result.error) { + responseText += `\n== Error ==\n${result.error}\n`; + if (result.stack) { + responseText += `\n${result.stack}\n`; + } + } + + return { + content: [{ type: "text", text: responseText }], + }; + } catch (error) { + // Handle any unexpected errors to prevent server crash + console.error("Error in execute_js_code:", error); + const errorMessage = error instanceof Error ? error.message : String(error); + const stack = error instanceof Error ? error.stack : "No stack trace"; + + return { + content: [{ + type: "text", + text: `Error executing JavaScript code: ${errorMessage}\n\nStack trace:\n${stack}` + }], + isError: true + }; + } + } default: throw new Error(`Unknown tool: ${name}`); diff --git a/src/filesystem/package.json b/src/filesystem/package.json index 6aca648fa4..0702a1eb72 100644 --- a/src/filesystem/package.json +++ b/src/filesystem/package.json @@ -22,13 +22,19 @@ "@modelcontextprotocol/sdk": "0.5.0", "diff": "^5.1.0", "glob": "^10.3.10", + "lodash": "^4.17.21", + "mathjs": "^12.3.0", "minimatch": "^10.0.1", + "papaparse": "^5.4.1", + "xlsx": "^0.18.5", "zod-to-json-schema": "^3.23.5" }, "devDependencies": { "@types/diff": "^5.0.9", + "@types/lodash": "^4.14.200", "@types/minimatch": "^5.1.2", "@types/node": "^22", + "@types/papaparse": "^5.3.14", "shx": "^0.3.4", "typescript": "^5.3.3" }