summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json1242
-rw-r--r--package.json6
-rw-r--r--packages/server/package.json3
-rw-r--r--packages/server/src/core/logger.test.ts503
-rw-r--r--packages/server/src/core/logger.ts290
5 files changed, 579 insertions, 1465 deletions
diff --git a/package-lock.json b/package-lock.json
index c0cec25f..8fa88e38 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,9 +10,6 @@
"workspaces": [
"packages/*"
],
- "dependencies": {
- "sqlite3": "^5.1.7"
- },
"bin": {
"gemini": "bundle/gemini.js"
},
@@ -871,13 +868,6 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@gar/promisify": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
- "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
- "license": "MIT",
- "optional": true
- },
"node_modules/@gemini-code/cli": {
"resolved": "packages/cli",
"link": true
@@ -1214,45 +1204,6 @@
"node": ">= 8"
}
},
- "node_modules/@npmcli/fs": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
- "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "@gar/promisify": "^1.0.1",
- "semver": "^7.3.5"
- }
- },
- "node_modules/@npmcli/fs/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@npmcli/move-file": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
- "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
- "deprecated": "This functionality has been moved to @npmcli/fs",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -1610,16 +1561,6 @@
"react-dom": "^18.0.0"
}
},
- "node_modules/@tootallnate/once": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
- "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/@types/aria-query": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
@@ -2145,13 +2086,6 @@
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "license": "ISC",
- "optional": true
- },
"node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@@ -2218,56 +2152,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "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",
- "optional": true,
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/agentkeepalive": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
- "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/aggregate-error/node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2323,28 +2207,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/aproba": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
- "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/are-we-there-yet": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
- "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -2572,7 +2434,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
"node_modules/base64-js": {
@@ -2604,26 +2466,6 @@
"node": "*"
}
},
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "license": "MIT",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
"node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
@@ -2648,7 +2490,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -2667,30 +2509,6 @@
"node": ">=8"
}
},
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -2731,36 +2549,6 @@
"node": ">=8"
}
},
- "node_modules/cacache": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
- "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "@npmcli/fs": "^1.0.0",
- "@npmcli/move-file": "^1.0.1",
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "glob": "^7.1.4",
- "infer-owner": "^1.0.4",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.1",
- "minipass-collect": "^1.0.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.2",
- "mkdirp": "^1.0.3",
- "p-map": "^4.0.0",
- "promise-inflight": "^1.0.1",
- "rimraf": "^3.0.2",
- "ssri": "^8.0.1",
- "tar": "^6.0.2",
- "unique-filename": "^1.1.1"
- },
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@@ -2862,25 +2650,6 @@
"node": ">= 16"
}
},
- "node_modules/chownr": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
- "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/cli-boxes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
@@ -3075,30 +2844,13 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
- "node_modules/color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "color-support": "bin.js"
- }
- },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
- "license": "ISC",
- "optional": true
- },
"node_modules/content-disposition": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
@@ -3287,21 +3039,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/deep-eql": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
@@ -3345,15 +3082,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -3437,13 +3165,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
- "license": "MIT",
- "optional": true
- },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -3462,15 +3183,6 @@
"node": ">=6"
}
},
- "node_modules/detect-libc": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
- "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/devlop": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
@@ -3582,19 +3294,11 @@
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"license": "MIT",
"optional": true,
+ "peer": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
},
- "node_modules/end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
"node_modules/entities": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
@@ -3608,16 +3312,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/environment": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
@@ -3630,13 +3324,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/err-code": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
- "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
- "license": "MIT",
- "optional": true
- },
"node_modules/es-abstract": {
"version": "1.23.10",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.10.tgz",
@@ -4294,15 +3981,6 @@
"node": ">=18.0.0"
}
},
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/expect-type": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz",
@@ -4481,12 +4159,6 @@
"node": ">=16.0.0"
}
},
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "license": "MIT"
- },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -4630,31 +4302,6 @@
"node": ">= 0.8"
}
},
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "license": "MIT"
- },
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "license": "ISC",
- "optional": true
- },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -4711,27 +4358,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/gauge": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
- "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.3",
- "console-control-strings": "^1.1.0",
- "has-unicode": "^2.0.1",
- "signal-exit": "^3.0.7",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.5"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/gaxios": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
@@ -4860,34 +4486,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "license": "MIT"
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -4969,13 +4567,6 @@
"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==",
- "license": "ISC",
- "optional": true
- },
"node_modules/gradient-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/gradient-string/-/gradient-string-2.0.2.tgz",
@@ -5088,13 +4679,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
- "license": "ISC",
- "optional": true
- },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -5154,13 +4738,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/http-cache-semantics": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
- "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
- "license": "BSD-2-Clause",
- "optional": true
- },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -5177,45 +4754,6 @@
"node": ">= 0.8"
}
},
- "node_modules/http-proxy-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
- "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tootallnate/once": "1",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "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",
- "optional": true,
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -5228,26 +4766,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "BSD-3-Clause"
- },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -5279,7 +4797,7 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.19"
@@ -5309,37 +4827,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "license": "ISC"
- },
"node_modules/ink": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/ink/-/ink-5.2.1.tgz",
@@ -5626,20 +5119,6 @@
"node": ">= 0.4"
}
},
- "node_modules/ip-address": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
- "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "jsbn": "1.1.0",
- "sprintf-js": "^1.1.3"
- },
- "engines": {
- "node": ">= 12"
- }
- },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -5917,13 +5396,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-lambda": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
- "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
- "license": "MIT",
- "optional": true
- },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -6280,13 +5752,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/jsbn": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
- "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
- "license": "MIT",
- "optional": true
- },
"node_modules/jsdom": {
"version": "26.1.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
@@ -6554,19 +6019,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/lz-string": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
@@ -6628,34 +6080,6 @@
"node": ">=10"
}
},
- "node_modules/make-fetch-happen": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
- "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "agentkeepalive": "^4.1.3",
- "cacache": "^15.2.0",
- "http-cache-semantics": "^4.1.0",
- "http-proxy-agent": "^4.0.1",
- "https-proxy-agent": "^5.0.0",
- "is-lambda": "^1.0.1",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.3",
- "minipass-collect": "^1.0.2",
- "minipass-fetch": "^1.3.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.4",
- "negotiator": "^0.6.2",
- "promise-retry": "^2.0.1",
- "socks-proxy-agent": "^6.0.0",
- "ssri": "^8.0.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -6738,23 +6162,11 @@
"node": ">=6"
}
},
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "devOptional": true,
+ "dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
@@ -6767,124 +6179,12 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-collect": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
- "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-fetch": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
- "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.0",
- "minipass-sized": "^1.0.3",
- "minizlib": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "optionalDependencies": {
- "encoding": "^0.1.12"
- }
- },
- "node_modules/minipass-flush": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
- "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-pipeline": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
- "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-sized": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
- "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^3.0.0",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "license": "MIT"
- },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -6910,12 +6210,6 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "license": "MIT"
- },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -6923,46 +6217,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/negotiator": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
- "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-abi": {
- "version": "3.75.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
- "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-abi/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-addon-api": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
- "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
- "license": "MIT"
- },
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@@ -7005,60 +6259,6 @@
"webidl-conversions": "^3.0.0"
}
},
- "node_modules/node-gyp": {
- "version": "8.4.1",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
- "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "env-paths": "^2.2.0",
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.6",
- "make-fetch-happen": "^9.1.0",
- "nopt": "^5.0.0",
- "npmlog": "^6.0.0",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.2",
- "which": "^2.0.2"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": ">= 10.12.0"
- }
- },
- "node_modules/node-gyp/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/nopt": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
- "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/normalize-package-data": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz",
@@ -7085,23 +6285,6 @@
"node": ">=10"
}
},
- "node_modules/npmlog": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
- "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "are-we-there-yet": "^3.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^4.0.3",
- "set-blocking": "^2.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
"node_modules/nwsapi": {
"version": "2.2.20",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz",
@@ -7369,22 +6552,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
@@ -7463,16 +6630,6 @@
"node": ">=8"
}
},
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -7615,32 +6772,6 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -7702,27 +6833,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/promise-retry": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
- "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "err-code": "^2.0.2",
- "retry": "^0.12.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -7747,16 +6857,6 @@
"node": ">= 0.10"
}
},
- "node_modules/pump": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
- "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
- "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",
@@ -7825,30 +6925,6 @@
"node": ">= 0.8"
}
},
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/rc/node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
@@ -7945,20 +7021,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "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/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -8069,16 +7131,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 4"
- }
- },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -8089,23 +7141,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/rollup": {
"version": "4.41.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.0.tgz",
@@ -8375,13 +7410,6 @@
"node": ">= 18"
}
},
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "license": "ISC",
- "optional": true
- },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -8555,51 +7583,6 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"license": "ISC"
},
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
"node_modules/slice-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
@@ -8643,47 +7626,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks": {
- "version": "2.8.4",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
- "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "ip-address": "^9.0.5",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks-proxy-agent": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
- "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "agent-base": "^6.0.2",
- "debug": "^4.3.3",
- "socks": "^2.6.2"
- },
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -8726,50 +7668,6 @@
"integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
"license": "CC0-1.0"
},
- "node_modules/sprintf-js": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
- "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
- "license": "BSD-3-Clause",
- "optional": true
- },
- "node_modules/sqlite3": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
- "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "bindings": "^1.5.0",
- "node-addon-api": "^7.0.0",
- "prebuild-install": "^7.1.1",
- "tar": "^6.1.11"
- },
- "optionalDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependenciesMeta": {
- "node-gyp": {
- "optional": true
- }
- }
- },
- "node_modules/ssri": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
- "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/stack-utils": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@@ -8828,15 +7726,6 @@
"node": ">= 0.4"
}
},
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@@ -9064,66 +7953,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/tar": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
- "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
- "license": "ISC",
- "dependencies": {
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "minipass": "^5.0.0",
- "minizlib": "^2.1.1",
- "mkdirp": "^1.0.3",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
- "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-fs/node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "license": "ISC"
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tar/node_modules/minipass": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
- "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
- "license": "ISC",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/test-exclude": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
@@ -9406,18 +8235,6 @@
"strip-bom": "^3.0.0"
}
},
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -9631,26 +8448,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "unique-slug": "^2.0.0"
- }
- },
- "node_modules/unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
- "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "imurmurhash": "^0.1.4"
- }
- },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -9669,12 +8466,6 @@
"punycode": "^2.1.0"
}
},
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
@@ -10085,16 +8876,6 @@
"node": ">=8"
}
},
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
"node_modules/widest-line": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz",
@@ -10322,12 +9103,6 @@
"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",
@@ -10495,8 +9270,7 @@
"diff": "^7.0.0",
"dotenv": "^16.4.7",
"fast-glob": "^3.3.3",
- "shell-quote": "^1.8.2",
- "sqlite3": "^5.1.7"
+ "shell-quote": "^1.8.2"
},
"devDependencies": {
"@types/diff": "^7.0.2",
diff --git a/package.json b/package.json
index 61366e41..82d18391 100644
--- a/package.json
+++ b/package.json
@@ -24,7 +24,7 @@
"auth:docker": "gcloud auth configure-docker us-west1-docker.pkg.dev",
"auth": "npm run auth:npm && npm run auth:docker",
"prerelease:dev": "npm run prerelease:version --workspaces && npm run prerelease:deps --workspaces",
- "bundle": "node_modules/.bin/esbuild packages/cli/index.ts --bundle --outfile=bundle/gemini.js --platform=node --format=esm --external:sqlite3 --banner:js=\"import { createRequire } from 'module'; const require = createRequire(import.meta.url); globalThis.__filename = require('url').fileURLToPath(import.meta.url); globalThis.__dirname = require('path').dirname(globalThis.__filename);\" && bash scripts/copy_bundle_assets.sh"
+ "bundle": "node_modules/.bin/esbuild packages/cli/index.ts --bundle --outfile=bundle/gemini.js --platform=node --format=esm --banner:js=\"import { createRequire } from 'module'; const require = createRequire(import.meta.url); globalThis.__filename = require('url').fileURLToPath(import.meta.url); globalThis.__dirname = require('path').dirname(globalThis.__filename);\" && bash scripts/copy_bundle_assets.sh"
},
"bin": {
"gemini": "bundle/gemini.js"
@@ -34,9 +34,7 @@
"README.md",
"LICENSE"
],
- "dependencies": {
- "sqlite3": "^5.1.7"
- },
+ "dependencies": {},
"devDependencies": {
"@types/mime-types": "^2.1.4",
"@vitest/coverage-v8": "^3.1.1",
diff --git a/packages/server/package.json b/packages/server/package.json
index a9bb8f94..8e654c88 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -27,8 +27,7 @@
"diff": "^7.0.0",
"dotenv": "^16.4.7",
"fast-glob": "^3.3.3",
- "shell-quote": "^1.8.2",
- "sqlite3": "^5.1.7"
+ "shell-quote": "^1.8.2"
},
"devDependencies": {
"@types/diff": "^7.0.2",
diff --git a/packages/server/src/core/logger.test.ts b/packages/server/src/core/logger.test.ts
index 9b4f4555..2663a6be 100644
--- a/packages/server/src/core/logger.test.ts
+++ b/packages/server/src/core/logger.test.ts
@@ -4,194 +4,429 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
-import { Logger, MessageSenderType } from './logger.js';
+import {
+ describe,
+ it,
+ expect,
+ vi,
+ beforeEach,
+ afterEach,
+ afterAll,
+} from 'vitest';
+import { Logger, MessageSenderType, LogEntry } from './logger.js';
+import { promises as fs } from 'node:fs';
+import path from 'node:path';
-// Mocks
-const mockDb = {
- exec: vi.fn((_sql, callback) => callback?.(null)),
- all: vi.fn((_sql, _params, callback) => callback?.(null, [])),
- run: vi.fn((_sql, _params, callback) => callback?.(null)),
- close: vi.fn((callback) => callback?.(null)),
-};
+const GEMINI_DIR = '.gemini';
+const LOG_FILE_NAME = 'logs.json';
+const TEST_LOG_FILE_PATH = path.join(process.cwd(), GEMINI_DIR, LOG_FILE_NAME);
-vi.mock('sqlite3', () => ({
- Database: vi.fn((_dbPath, _options, callback) => {
- process.nextTick(() => callback?.(null));
- return mockDb;
- }),
- default: {
- Database: vi.fn((_dbPath, _options, callback) => {
- process.nextTick(() => callback?.(null));
- return mockDb;
- }),
- },
-}));
+async function cleanupLogFile() {
+ try {
+ await fs.unlink(TEST_LOG_FILE_PATH);
+ } catch (error) {
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
+ // Other errors during unlink are ignored for cleanup purposes
+ }
+ }
+ try {
+ const geminiDirPath = path.join(process.cwd(), GEMINI_DIR);
+ const dirContents = await fs.readdir(geminiDirPath);
+ for (const file of dirContents) {
+ if (file.startsWith(LOG_FILE_NAME + '.') && file.endsWith('.bak')) {
+ try {
+ await fs.unlink(path.join(geminiDirPath, file));
+ } catch (_e) {
+ /* ignore */
+ }
+ }
+ }
+ } catch (error) {
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
+ /* ignore if .gemini dir itself is missing */
+ }
+ }
+}
+
+async function readLogFile(): Promise<LogEntry[]> {
+ try {
+ const content = await fs.readFile(TEST_LOG_FILE_PATH, 'utf-8');
+ return JSON.parse(content) as LogEntry[];
+ } catch (error) {
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
+ return [];
+ }
+ throw error;
+ }
+}
describe('Logger', () => {
let logger: Logger;
beforeEach(async () => {
- vi.resetAllMocks();
-
- // Get a new instance for each test to ensure isolation,
+ vi.useFakeTimers();
+ vi.setSystemTime(new Date('2025-01-01T12:00:00.000Z'));
+ await cleanupLogFile();
logger = new Logger();
- // We need to wait for the async initialize to complete
- await logger.initialize().catch((err) => {
- console.error('Error initializing logger:', err);
- });
+ // Initialize is usually called here, but some tests initialize their own instances.
+ // For tests that use the global `logger`, it will be initialized here.
+ await logger.initialize();
+ });
+
+ afterEach(async () => {
+ logger.close();
+ await cleanupLogFile();
+ vi.useRealTimers();
+ vi.resetAllMocks(); // Ensure mocks are reset for every test
});
- afterEach(() => {
- vi.restoreAllMocks();
- logger.close(); // Close the database connection after each test
+ afterAll(async () => {
+ await cleanupLogFile();
});
describe('initialize', () => {
- it('should execute create tables if not exists', async () => {
- expect(mockDb.exec).toHaveBeenCalledWith(
- expect.stringMatching(/CREATE TABLE IF NOT EXISTS messages/),
- expect.any(Function),
- );
+ it('should create .gemini directory and an empty log file if none exist', async () => {
+ await cleanupLogFile();
+ const geminiDirPath = path.join(process.cwd(), GEMINI_DIR);
+ try {
+ await fs.rm(geminiDirPath, { recursive: true, force: true });
+ } catch (_e) {
+ /* ignore */
+ }
+
+ const newLogger = new Logger();
+ await newLogger.initialize();
+
+ const dirExists = await fs
+ .access(geminiDirPath)
+ .then(() => true)
+ .catch(() => false);
+ expect(dirExists).toBe(true);
+ const fileExists = await fs
+ .access(TEST_LOG_FILE_PATH)
+ .then(() => true)
+ .catch(() => false);
+ expect(fileExists).toBe(true);
+ const logContent = await readLogFile();
+ expect(logContent).toEqual([]);
+ newLogger.close();
});
- it('should be idempotent', async () => {
- mockDb.exec.mockClear();
+ it('should load existing logs and set correct messageId for the current session', async () => {
+ const fixedTime = new Date('2025-01-01T10:00:00.000Z');
+ vi.setSystemTime(fixedTime);
+ const currentSessionId = Math.floor(fixedTime.getTime() / 1000);
+ const existingLogs: LogEntry[] = [
+ {
+ sessionId: currentSessionId,
+ messageId: 0,
+ timestamp: new Date('2025-01-01T10:00:05.000Z').toISOString(),
+ type: MessageSenderType.USER,
+ message: 'Msg1',
+ },
+ {
+ sessionId: currentSessionId - 100,
+ messageId: 5,
+ timestamp: new Date('2025-01-01T09:00:00.000Z').toISOString(),
+ type: MessageSenderType.USER,
+ message: 'OldMsg',
+ },
+ {
+ sessionId: currentSessionId,
+ messageId: 1,
+ timestamp: new Date('2025-01-01T10:00:10.000Z').toISOString(),
+ type: MessageSenderType.USER,
+ message: 'Msg2',
+ },
+ ];
+ await fs.mkdir(path.join(process.cwd(), GEMINI_DIR), { recursive: true });
+ await fs.writeFile(TEST_LOG_FILE_PATH, JSON.stringify(existingLogs));
+ const newLogger = new Logger();
+ await newLogger.initialize();
+ expect(newLogger['messageId']).toBe(2);
+ expect(newLogger['logs']).toEqual(existingLogs);
+ newLogger.close();
+ });
- await logger.initialize(); // Second call
+ it('should set messageId to 0 for a new session if log file exists but has no logs for current session', async () => {
+ const fixedTime = new Date('2025-01-01T14:00:00.000Z');
+ vi.setSystemTime(fixedTime);
+ const existingLogs: LogEntry[] = [
+ {
+ sessionId: Math.floor(fixedTime.getTime() / 1000) - 500,
+ messageId: 5,
+ timestamp: new Date().toISOString(),
+ type: MessageSenderType.USER,
+ message: 'OldMsg',
+ },
+ ];
+ await fs.mkdir(path.join(process.cwd(), GEMINI_DIR), { recursive: true });
+ await fs.writeFile(TEST_LOG_FILE_PATH, JSON.stringify(existingLogs));
+ const newLogger = new Logger();
+ await newLogger.initialize();
+ expect(newLogger['messageId']).toBe(0);
+ newLogger.close();
+ });
- expect(mockDb.exec).not.toHaveBeenCalled();
+ it('should be idempotent', async () => {
+ // logger is initialized in beforeEach
+ await logger.logMessage(MessageSenderType.USER, 'test message');
+ const initialMessageId = logger['messageId'];
+ const initialLogCount = logger['logs'].length;
+ await logger.initialize(); // Second call should not change state
+ expect(logger['messageId']).toBe(initialMessageId);
+ expect(logger['logs'].length).toBe(initialLogCount);
+ const logsFromFile = await readLogFile();
+ expect(logsFromFile.length).toBe(1);
});
- });
- describe('logMessage', () => {
- it('should insert a message into the database', async () => {
- const type = MessageSenderType.USER;
- const message = 'Hello, world!';
- await logger.logMessage(type, message);
- expect(mockDb.run).toHaveBeenCalledWith(
- "INSERT INTO messages (session_id, message_id, type, message, timestamp) VALUES (?, ?, ?, ?, datetime('now'))",
- [expect.any(Number), 0, type, message], // sessionId, messageId, type, message
- expect.any(Function),
+ it('should handle invalid JSON in log file by backing it up and starting fresh', async () => {
+ await fs.mkdir(path.join(process.cwd(), GEMINI_DIR), { recursive: true });
+ await fs.writeFile(TEST_LOG_FILE_PATH, 'invalid json');
+ const consoleDebugSpy = vi
+ .spyOn(console, 'debug')
+ .mockImplementation(() => {});
+ const newLogger = new Logger();
+ await newLogger.initialize();
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
+ expect.stringContaining('Invalid JSON in log file'),
+ expect.any(SyntaxError),
);
+ const logContent = await readLogFile();
+ expect(logContent).toEqual([]);
+ const dirContents = await fs.readdir(
+ path.join(process.cwd(), GEMINI_DIR),
+ );
+ expect(
+ dirContents.some(
+ (f) =>
+ f.startsWith(LOG_FILE_NAME + '.invalid_json') && f.endsWith('.bak'),
+ ),
+ ).toBe(true);
+ consoleDebugSpy.mockRestore();
+ newLogger.close();
});
- it('should increment messageId for subsequent messages', async () => {
- await logger.logMessage(MessageSenderType.USER, 'First message');
- expect(mockDb.run).toHaveBeenCalledWith(
- expect.any(String),
- [expect.any(Number), 0, MessageSenderType.USER, 'First message'],
- expect.any(Function),
+ it('should handle non-array JSON in log file by backing it up and starting fresh', async () => {
+ await fs.mkdir(path.join(process.cwd(), GEMINI_DIR), { recursive: true });
+ await fs.writeFile(
+ TEST_LOG_FILE_PATH,
+ JSON.stringify({ not: 'an array' }),
);
- await logger.logMessage(MessageSenderType.USER, 'Second message');
- expect(mockDb.run).toHaveBeenCalledWith(
- expect.any(String),
- [expect.any(Number), 1, MessageSenderType.USER, 'Second message'], // messageId is now 1
- expect.any(Function),
+ const consoleDebugSpy = vi
+ .spyOn(console, 'debug')
+ .mockImplementation(() => {});
+ const newLogger = new Logger();
+ await newLogger.initialize();
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
+ `Log file at ${TEST_LOG_FILE_PATH} is not a valid JSON array. Starting with empty logs.`,
);
+ const logContent = await readLogFile();
+ expect(logContent).toEqual([]);
+ const dirContents = await fs.readdir(
+ path.join(process.cwd(), GEMINI_DIR),
+ );
+ expect(
+ dirContents.some(
+ (f) =>
+ f.startsWith(LOG_FILE_NAME + '.malformed_array') &&
+ f.endsWith('.bak'),
+ ),
+ ).toBe(true);
+ consoleDebugSpy.mockRestore();
+ newLogger.close();
+ });
+ });
+
+ describe('logMessage', () => {
+ it('should append a message to the log file and update in-memory logs', async () => {
+ await logger.logMessage(MessageSenderType.USER, 'Hello, world!');
+ const logsFromFile = await readLogFile();
+ expect(logsFromFile.length).toBe(1);
+ expect(logsFromFile[0]).toMatchObject({
+ sessionId: logger['sessionId'],
+ messageId: 0,
+ type: MessageSenderType.USER,
+ message: 'Hello, world!',
+ timestamp: new Date('2025-01-01T12:00:00.000Z').toISOString(),
+ });
+ expect(logger['logs'].length).toBe(1);
+ expect(logger['logs'][0]).toEqual(logsFromFile[0]);
+ expect(logger['messageId']).toBe(1);
+ });
+
+ it('should correctly increment messageId for subsequent messages in the same session', async () => {
+ await logger.logMessage(MessageSenderType.USER, 'First');
+ vi.advanceTimersByTime(1000);
+ await logger.logMessage(MessageSenderType.USER, 'Second');
+ const logs = await readLogFile();
+ expect(logs.length).toBe(2);
+ expect(logs[0].messageId).toBe(0);
+ expect(logs[1].messageId).toBe(1);
+ expect(logs[1].timestamp).not.toBe(logs[0].timestamp);
+ expect(logger['messageId']).toBe(2);
});
- it('should handle database not initialized', async () => {
+ it('should handle logger not initialized', async () => {
const uninitializedLogger = new Logger();
- // uninitializedLogger.initialize() is not called
- const consoleErrorSpy = vi
- .spyOn(console, 'error')
+ const consoleDebugSpy = vi
+ .spyOn(console, 'debug')
.mockImplementation(() => {});
-
await uninitializedLogger.logMessage(MessageSenderType.USER, 'test');
-
- expect(consoleErrorSpy).toHaveBeenCalledWith('Database not initialized.');
- expect(mockDb.run).not.toHaveBeenCalled();
- consoleErrorSpy.mockRestore();
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
+ 'Logger not initialized or session ID missing. Cannot log message.',
+ );
+ expect((await readLogFile()).length).toBe(0);
+ consoleDebugSpy.mockRestore();
+ uninitializedLogger.close();
});
- it('should handle error during db.run', async () => {
- const error = new Error('db.run failed');
- mockDb.run.mockImplementationOnce(
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (_sql: any, _params: any, callback: any) => callback?.(error),
- );
+ it('should simulate concurrent writes from different logger instances to the same file', async () => {
+ const logger1 = new Logger(); // logger1
+ vi.setSystemTime(new Date('2025-01-01T13:00:00.000Z'));
+ await logger1.initialize();
+ const s1 = logger1['sessionId'];
- await expect(
- logger.logMessage(MessageSenderType.USER, 'test'),
- ).rejects.toThrow('db.run failed');
- });
- });
+ const logger2 = new Logger(); // logger2, will share same session if time is same
+ vi.setSystemTime(new Date('2025-01-01T13:00:00.000Z'));
+ await logger2.initialize();
+ expect(logger2['sessionId']).toEqual(s1);
- describe('getPreviousUserMessages', () => {
- it('should query the database for messages', async () => {
- mockDb.all.mockImplementationOnce(
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (_sql: any, params: any, callback: any) =>
- callback?.(null, [{ message: 'msg1' }, { message: 'msg2' }]),
- );
+ // Log from logger1
+ await logger1.logMessage(MessageSenderType.USER, 'L1M1'); // L1 internal msgId becomes 1, writes {s1, 0}
+ vi.advanceTimersByTime(10);
- const messages = await logger.getPreviousUserMessages();
+ // Log from logger2. It reads file (sees {s1,0}), its internal msgId for s1 is 1.
+ await logger2.logMessage(MessageSenderType.USER, 'L2M1'); // L2 internal msgId becomes 2, writes {s1, 1}
+ vi.advanceTimersByTime(10);
- expect(mockDb.all).toHaveBeenCalledWith(
- expect.stringMatching(/SELECT message FROM messages/),
- [],
- expect.any(Function),
- );
- expect(messages).toEqual(['msg1', 'msg2']);
+ // Log from logger1. It reads file (sees {s1,0}, {s1,1}), its internal msgId for s1 is 2.
+ await logger1.logMessage(MessageSenderType.USER, 'L1M2'); // L1 internal msgId becomes 3, writes {s1, 2}
+ vi.advanceTimersByTime(10);
+
+ // Log from logger2. It reads file (sees {s1,0}, {s1,1}, {s1,2}), its internal msgId for s1 is 3.
+ await logger2.logMessage(MessageSenderType.USER, 'L2M2'); // L2 internal msgId becomes 4, writes {s1, 3}
+
+ const logsFromFile = await readLogFile();
+ expect(logsFromFile.length).toBe(4);
+ const messageIdsInFile = logsFromFile
+ .map((log) => log.messageId)
+ .sort((a, b) => a - b);
+ expect(messageIdsInFile).toEqual([0, 1, 2, 3]);
+
+ const messagesInFile = logsFromFile
+ .sort((a, b) => a.messageId - b.messageId)
+ .map((l) => l.message);
+ expect(messagesInFile).toEqual(['L1M1', 'L2M1', 'L1M2', 'L2M2']);
+
+ // Check internal state (next messageId each logger would use for that session)
+ expect(logger1['messageId']).toBe(3); // L1 wrote 0, then 2. Next is 3.
+ expect(logger2['messageId']).toBe(4); // L2 wrote 1, then 3. Next is 4.
+
+ logger1.close();
+ logger2.close();
});
- it('should handle database not initialized', async () => {
- const uninitializedLogger = new Logger();
- // uninitializedLogger.initialize() is not called
- const consoleErrorSpy = vi
- .spyOn(console, 'error')
+ it('should not throw, not increment messageId, and log error if writing to file fails', async () => {
+ const writeFileSpy = vi
+ .spyOn(fs, 'writeFile')
+ .mockRejectedValueOnce(new Error('Disk full'));
+ const consoleDebugSpy = vi
+ .spyOn(console, 'debug')
.mockImplementation(() => {});
+ const initialMessageId = logger['messageId'];
+ const initialLogCount = logger['logs'].length;
- const messages = await uninitializedLogger.getPreviousUserMessages();
+ await logger.logMessage(MessageSenderType.USER, 'test fail write');
- expect(consoleErrorSpy).toHaveBeenCalledWith('Database not initialized.');
- expect(messages).toEqual([]);
- expect(mockDb.all).not.toHaveBeenCalled();
- consoleErrorSpy.mockRestore();
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
+ 'Error writing to log file:',
+ expect.any(Error),
+ );
+ expect(logger['messageId']).toBe(initialMessageId); // Not incremented
+ expect(logger['logs'].length).toBe(initialLogCount); // Log not added to in-memory cache
+
+ writeFileSpy.mockRestore();
+ consoleDebugSpy.mockRestore();
});
+ });
- it('should handle error during db.all', async () => {
- const error = new Error('db.all failed');
- mockDb.all.mockImplementationOnce(
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (_sql: any, _params: any, callback: any) => callback?.(error, []),
- );
+ describe('getPreviousUserMessages', () => {
+ it('should retrieve user messages, sorted newest first by session, then timestamp, then messageId', async () => {
+ const loggerSort = new Logger();
+ vi.setSystemTime(new Date('2025-01-01T10:00:00.000Z'));
+ await loggerSort.initialize();
+ const s1 = loggerSort['sessionId']!;
+ await loggerSort.logMessage(MessageSenderType.USER, 'S1M0_ts100000'); // msgId 0
+ vi.advanceTimersByTime(10);
+ await loggerSort.logMessage(MessageSenderType.USER, 'S1M1_ts100010'); // msgId 1
+ loggerSort.close(); // Close to ensure next initialize starts a new session if time changed
- await expect(logger.getPreviousUserMessages()).rejects.toThrow(
- 'db.all failed',
+ vi.setSystemTime(new Date('2025-01-01T11:00:00.000Z'));
+ await loggerSort.initialize(); // Re-initialize for a new session
+ const s2 = loggerSort['sessionId']!;
+ expect(s2).not.toEqual(s1);
+ await loggerSort.logMessage(MessageSenderType.USER, 'S2M0_ts110000'); // msgId 0 for s2
+ vi.advanceTimersByTime(10);
+ await loggerSort.logMessage(
+ 'model' as MessageSenderType,
+ 'S2_Model_ts110010',
);
+ vi.advanceTimersByTime(10);
+ await loggerSort.logMessage(MessageSenderType.USER, 'S2M1_ts110020'); // msgId 1 for s2
+ loggerSort.close();
+
+ // To test the sorting thoroughly, especially the session part, we'll read the file
+ // as if it was written by multiple sessions and then initialize a new logger to load them.
+ const combinedLogs = await readLogFile();
+ const finalLogger = new Logger();
+ // Manually set its internal logs to simulate loading from a file with mixed sessions
+ finalLogger['logs'] = combinedLogs;
+ finalLogger['initialized'] = true; // Mark as initialized to allow getPreviousUserMessages to run
+
+ const messages = await finalLogger.getPreviousUserMessages();
+ expect(messages).toEqual([
+ 'S2M1_ts110020',
+ 'S2M0_ts110000',
+ 'S1M1_ts100010',
+ 'S1M0_ts100000',
+ ]);
+ finalLogger.close();
});
- });
- describe('close', () => {
- it('should close the database connection', () => {
- logger.close();
- expect(mockDb.close).toHaveBeenCalled();
+ it('should return empty array if no user messages exist', async () => {
+ await logger.logMessage('system' as MessageSenderType, 'System boot');
+ const messages = await logger.getPreviousUserMessages();
+ expect(messages).toEqual([]);
});
- it('should handle database not initialized', () => {
+ it('should return empty array if logger not initialized', async () => {
const uninitializedLogger = new Logger();
- // uninitializedLogger.initialize() is not called
+ const messages = await uninitializedLogger.getPreviousUserMessages();
+ expect(messages).toEqual([]);
uninitializedLogger.close();
- expect(() => uninitializedLogger.close()).not.toThrow();
});
+ });
- it('should handle error during db.close', () => {
- const error = new Error('db.close failed');
- mockDb.close.mockImplementationOnce((callback: (error: Error) => void) =>
- callback?.(error),
- );
- const consoleErrorSpy = vi
- .spyOn(console, 'error')
- .mockImplementation(() => {});
-
+ describe('close', () => {
+ it('should reset logger state', async () => {
+ await logger.logMessage(MessageSenderType.USER, 'A message');
logger.close();
- expect(consoleErrorSpy).toHaveBeenCalledWith(
- 'Error closing database:',
- error.message,
+ const consoleDebugSpy = vi
+ .spyOn(console, 'debug')
+ .mockImplementation(() => {});
+ await logger.logMessage(MessageSenderType.USER, 'Another message');
+ expect(consoleDebugSpy).toHaveBeenCalledWith(
+ 'Logger not initialized or session ID missing. Cannot log message.',
);
- consoleErrorSpy.mockRestore();
+ const messages = await logger.getPreviousUserMessages();
+ expect(messages).toEqual([]);
+ expect(logger['initialized']).toBe(false);
+ expect(logger['logFilePath']).toBeUndefined();
+ expect(logger['logs']).toEqual([]);
+ expect(logger['sessionId']).toBeUndefined();
+ expect(logger['messageId']).toBe(0);
+ consoleDebugSpy.mockRestore();
});
});
});
diff --git a/packages/server/src/core/logger.ts b/packages/server/src/core/logger.ts
index d12d4240..feb16944 100644
--- a/packages/server/src/core/logger.ts
+++ b/packages/server/src/core/logger.ts
@@ -5,127 +5,235 @@
*/
import path from 'node:path';
-import sqlite3 from 'sqlite3';
import { promises as fs } from 'node:fs';
const GEMINI_DIR = '.gemini';
-const DB_NAME = 'logs.db';
-const CREATE_TABLE_SQL = `
-CREATE TABLE IF NOT EXISTS messages (
- session_id INTEGER,
- message_id INTEGER,
- timestamp TEXT,
- type TEXT,
- message TEXT
-);`;
+const LOG_FILE_NAME = 'logs.json';
export enum MessageSenderType {
USER = 'user',
}
+export interface LogEntry {
+ sessionId: number;
+ messageId: number;
+ timestamp: string;
+ type: MessageSenderType;
+ message: string;
+}
+
export class Logger {
- private db: sqlite3.Database | undefined;
+ private logFilePath: string | undefined;
private sessionId: number | undefined;
- private messageId: number | undefined;
+ private messageId = 0; // Instance-specific counter for the next messageId
+ private initialized = false;
+ private logs: LogEntry[] = []; // In-memory cache, ideally reflects the last known state of the file
constructor() {}
+ private async _readLogFile(): Promise<LogEntry[]> {
+ if (!this.logFilePath) {
+ throw new Error('Log file path not set during read attempt.');
+ }
+ try {
+ const fileContent = await fs.readFile(this.logFilePath, 'utf-8');
+ const parsedLogs = JSON.parse(fileContent);
+ if (!Array.isArray(parsedLogs)) {
+ console.debug(
+ `Log file at ${this.logFilePath} is not a valid JSON array. Starting with empty logs.`,
+ );
+ await this._backupCorruptedLogFile('malformed_array');
+ return [];
+ }
+ return parsedLogs.filter(
+ (entry) =>
+ typeof entry.sessionId === 'number' &&
+ typeof entry.messageId === 'number' &&
+ typeof entry.timestamp === 'string' &&
+ typeof entry.type === 'string' &&
+ typeof entry.message === 'string',
+ ) as LogEntry[];
+ } catch (error) {
+ const nodeError = error as NodeJS.ErrnoException;
+ if (nodeError.code === 'ENOENT') {
+ return [];
+ }
+ if (error instanceof SyntaxError) {
+ console.debug(
+ `Invalid JSON in log file ${this.logFilePath}. Backing up and starting fresh.`,
+ error,
+ );
+ await this._backupCorruptedLogFile('invalid_json');
+ return [];
+ }
+ console.debug(
+ `Failed to read or parse log file ${this.logFilePath}:`,
+ error,
+ );
+ throw error;
+ }
+ }
+
+ private async _backupCorruptedLogFile(reason: string): Promise<void> {
+ if (!this.logFilePath) return;
+ const backupPath = `${this.logFilePath}.${reason}.${Date.now()}.bak`;
+ try {
+ await fs.rename(this.logFilePath, backupPath);
+ console.debug(`Backed up corrupted log file to ${backupPath}`);
+ } catch (_backupError) {
+ // If rename fails (e.g. file doesn't exist), no need to log an error here as the primary error (e.g. invalid JSON) is already handled.
+ }
+ }
+
async initialize(): Promise<void> {
- if (this.db) {
+ if (this.initialized) {
return;
}
-
this.sessionId = Math.floor(Date.now() / 1000);
- this.messageId = 0;
-
- // Could be cleaner if our sqlite package supported promises.
- return new Promise((resolve, reject) => {
- const DB_DIR = path.resolve(process.cwd(), GEMINI_DIR);
- const DB_PATH = path.join(DB_DIR, DB_NAME);
- fs.mkdir(DB_DIR, { recursive: true })
- .then(() => {
- this.db = new sqlite3.Database(
- DB_PATH,
- sqlite3.OPEN_READWRITE |
- sqlite3.OPEN_CREATE |
- sqlite3.OPEN_FULLMUTEX,
- (err: Error | null) => {
- if (err) {
- reject(err);
- }
+ const geminiDir = path.resolve(process.cwd(), GEMINI_DIR);
+ this.logFilePath = path.join(geminiDir, LOG_FILE_NAME);
- // Read and execute the SQL script in create_tables.sql
- this.db?.exec(CREATE_TABLE_SQL, (err: Error | null) => {
- if (err) {
- this.db?.close();
- reject(err);
- }
- resolve();
- });
- },
- );
- })
- .catch(reject);
- });
+ try {
+ await fs.mkdir(geminiDir, { recursive: true });
+ let fileExisted = true;
+ try {
+ await fs.access(this.logFilePath);
+ } catch (_e) {
+ fileExisted = false;
+ }
+ this.logs = await this._readLogFile();
+ if (!fileExisted && this.logs.length === 0) {
+ await fs.writeFile(this.logFilePath, '[]', 'utf-8');
+ }
+ const sessionLogs = this.logs.filter(
+ (entry) => entry.sessionId === this.sessionId,
+ );
+ this.messageId =
+ sessionLogs.length > 0
+ ? Math.max(...sessionLogs.map((entry) => entry.messageId)) + 1
+ : 0;
+ this.initialized = true;
+ } catch (err) {
+ console.error('Failed to initialize logger:', err);
+ this.initialized = false;
+ }
}
- /**
- * Get list of previous user inputs sorted most recent first.
- * @returns list of messages.
- */
- async getPreviousUserMessages(): Promise<string[]> {
- if (!this.db) {
- console.error('Database not initialized.');
- return [];
+ private async _updateLogFile(
+ entryToAppend: LogEntry,
+ ): Promise<LogEntry | null> {
+ if (!this.logFilePath) {
+ console.debug('Log file path not set. Cannot persist log entry.');
+ throw new Error('Log file path not set during update attempt.');
+ }
+
+ let currentLogsOnDisk: LogEntry[];
+ try {
+ currentLogsOnDisk = await this._readLogFile();
+ } catch (readError) {
+ console.debug(
+ 'Critical error reading log file before append:',
+ readError,
+ );
+ throw readError;
}
- return new Promise((resolve, reject) => {
- // Most recent messages first
- const query = `SELECT message FROM messages
- WHERE type = '${MessageSenderType.USER}'
- ORDER BY session_id DESC, message_id DESC`;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.db!.all(query, [], (err: Error | null, rows: any[]) => {
- if (err) {
- reject(err);
- } else {
- resolve(rows.map((row) => row.message));
- }
- });
- });
+ // Determine the correct messageId for the new entry based on current disk state for its session
+ const sessionLogsOnDisk = currentLogsOnDisk.filter(
+ (e) => e.sessionId === entryToAppend.sessionId,
+ );
+ const nextMessageIdForSession =
+ sessionLogsOnDisk.length > 0
+ ? Math.max(...sessionLogsOnDisk.map((e) => e.messageId)) + 1
+ : 0;
+
+ // Update the messageId of the entry we are about to append
+ entryToAppend.messageId = nextMessageIdForSession;
+
+ // Check if this entry (same session, same *recalculated* messageId, same content) might already exist
+ // This is a stricter check for true duplicates if multiple instances try to log the exact same thing
+ // at the exact same calculated messageId slot.
+ const entryExists = currentLogsOnDisk.some(
+ (e) =>
+ e.sessionId === entryToAppend.sessionId &&
+ e.messageId === entryToAppend.messageId &&
+ e.timestamp === entryToAppend.timestamp && // Timestamps are good for distinguishing
+ e.message === entryToAppend.message,
+ );
+
+ if (entryExists) {
+ console.debug(
+ `Duplicate log entry detected and skipped: session ${entryToAppend.sessionId}, messageId ${entryToAppend.messageId}`,
+ );
+ this.logs = currentLogsOnDisk; // Ensure in-memory is synced with disk
+ return null; // Indicate that no new entry was actually added
+ }
+
+ currentLogsOnDisk.push(entryToAppend);
+
+ try {
+ await fs.writeFile(
+ this.logFilePath,
+ JSON.stringify(currentLogsOnDisk, null, 2),
+ 'utf-8',
+ );
+ this.logs = currentLogsOnDisk;
+ return entryToAppend; // Return the successfully appended entry
+ } catch (error) {
+ console.debug('Error writing to log file:', error);
+ throw error;
+ }
+ }
+
+ async getPreviousUserMessages(): Promise<string[]> {
+ if (!this.initialized) return [];
+ return this.logs
+ .filter((entry) => entry.type === MessageSenderType.USER)
+ .sort((a, b) => {
+ if (b.sessionId !== a.sessionId) return b.sessionId - a.sessionId;
+ const dateA = new Date(a.timestamp).getTime();
+ const dateB = new Date(b.timestamp).getTime();
+ if (dateB !== dateA) return dateB - dateA;
+ return b.messageId - a.messageId;
+ })
+ .map((entry) => entry.message);
}
async logMessage(type: MessageSenderType, message: string): Promise<void> {
- if (!this.db) {
- console.error('Database not initialized.');
+ if (!this.initialized || this.sessionId === undefined) {
+ console.debug(
+ 'Logger not initialized or session ID missing. Cannot log message.',
+ );
return;
}
- return new Promise((resolve, reject) => {
- const query = `INSERT INTO messages (session_id, message_id, type, message, timestamp) VALUES (?, ?, ?, ?, datetime('now'))`;
- this.messageId = this.messageId! + 1;
- this.db!.run(
- query,
- [this.sessionId || 0, this.messageId - 1, type, message],
- (err: Error | null) => {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
- },
- );
- });
+ // The messageId used here is the instance's idea of the next ID.
+ // _updateLogFile will verify and potentially recalculate based on the file's actual state.
+ const newEntryObject: LogEntry = {
+ sessionId: this.sessionId,
+ messageId: this.messageId, // This will be recalculated in _updateLogFile
+ type,
+ message,
+ timestamp: new Date().toISOString(),
+ };
+
+ try {
+ const writtenEntry = await this._updateLogFile(newEntryObject);
+ if (writtenEntry) {
+ // If an entry was actually written (not a duplicate skip),
+ // then this instance can increment its idea of the next messageId for this session.
+ this.messageId = writtenEntry.messageId + 1;
+ }
+ } catch (_error) {
+ // Error already logged by _updateLogFile or _readLogFile
+ }
}
close(): void {
- if (this.db) {
- this.db.close((err: Error | null) => {
- if (err) {
- console.error('Error closing database:', err.message);
- }
- });
- this.db = undefined;
- }
+ this.initialized = false;
+ this.logFilePath = undefined;
+ this.logs = [];
+ this.sessionId = undefined;
+ this.messageId = 0;
}
}