From 7b2a429fa05fd700bfbfd7a98a7ffc4370be66c7 Mon Sep 17 00:00:00 2001 From: Zou Zhao Date: Sun, 20 Sep 2026 06:17:59 +0800 Subject: [PATCH 1/5] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=20package.json?= =?UTF-8?q?=20=E4=B8=AD=20mpget=20=E8=87=AA=20link=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- pnpm-lock.yaml | 2543 ++++++++++++++++-------------------------------- 2 files changed, 833 insertions(+), 1713 deletions(-) diff --git a/package.json b/package.json index 57a98ac..75704fc 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "cheerio": "^1.0.0", - "commander": "^12.0.0", - "mpget": "link:" + "commander": "^12.0.0" }, "devDependencies": { "@eslint/js": "^10.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5372229..63b358b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -251,16 +251,17 @@ snapshots: pnpm@11.1.2: {} --- -lockfileVersion: "9.0" +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false importers: + .: dependencies: - "@modelcontextprotocol/sdk": + '@modelcontextprotocol/sdk': specifier: ^1.29.0 version: 1.29.0(zod@4.4.3) cheerio: @@ -269,14 +270,11 @@ importers: commander: specifier: ^12.0.0 version: 12.1.0 - mpget: - specifier: "link:" - version: "link:" devDependencies: - "@eslint/js": + '@eslint/js': specifier: ^10.0.1 version: 10.0.1(eslint@10.5.0) - "@types/node": + '@types/node': specifier: ^22.0.0 version: 22.19.19 eslint: @@ -299,721 +297,464 @@ importers: version: 3.2.4(@types/node@22.19.19) packages: - "@esbuild/aix-ppc64@0.27.7": - resolution: - { - integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==, - } - engines: { node: ">=18" } + + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] - "@esbuild/android-arm64@0.27.7": - resolution: - { - integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==, - } - engines: { node: ">=18" } + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - "@esbuild/android-arm@0.27.7": - resolution: - { - integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==, - } - engines: { node: ">=18" } + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} cpu: [arm] os: [android] - "@esbuild/android-x64@0.27.7": - resolution: - { - integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==, - } - engines: { node: ">=18" } + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} cpu: [x64] os: [android] - "@esbuild/darwin-arm64@0.27.7": - resolution: - { - integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==, - } - engines: { node: ">=18" } + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - "@esbuild/darwin-x64@0.27.7": - resolution: - { - integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==, - } - engines: { node: ">=18" } + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - "@esbuild/freebsd-arm64@0.27.7": - resolution: - { - integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==, - } - engines: { node: ">=18" } + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - "@esbuild/freebsd-x64@0.27.7": - resolution: - { - integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==, - } - engines: { node: ">=18" } + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - "@esbuild/linux-arm64@0.27.7": - resolution: - { - integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==, - } - engines: { node: ">=18" } + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - "@esbuild/linux-arm@0.27.7": - resolution: - { - integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==, - } - engines: { node: ">=18" } + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - "@esbuild/linux-ia32@0.27.7": - resolution: - { - integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==, - } - engines: { node: ">=18" } + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - "@esbuild/linux-loong64@0.27.7": - resolution: - { - integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==, - } - engines: { node: ">=18" } + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - "@esbuild/linux-mips64el@0.27.7": - resolution: - { - integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==, - } - engines: { node: ">=18" } + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - "@esbuild/linux-ppc64@0.27.7": - resolution: - { - integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==, - } - engines: { node: ">=18" } + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - "@esbuild/linux-riscv64@0.27.7": - resolution: - { - integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==, - } - engines: { node: ">=18" } + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - "@esbuild/linux-s390x@0.27.7": - resolution: - { - integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==, - } - engines: { node: ">=18" } + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - "@esbuild/linux-x64@0.27.7": - resolution: - { - integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==, - } - engines: { node: ">=18" } + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - "@esbuild/netbsd-arm64@0.27.7": - resolution: - { - integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==, - } - engines: { node: ">=18" } + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - "@esbuild/netbsd-x64@0.27.7": - resolution: - { - integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==, - } - engines: { node: ">=18" } + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - "@esbuild/openbsd-arm64@0.27.7": - resolution: - { - integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==, - } - engines: { node: ">=18" } + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - "@esbuild/openbsd-x64@0.27.7": - resolution: - { - integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==, - } - engines: { node: ">=18" } + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - "@esbuild/openharmony-arm64@0.27.7": - resolution: - { - integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==, - } - engines: { node: ">=18" } + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - "@esbuild/sunos-x64@0.27.7": - resolution: - { - integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==, - } - engines: { node: ">=18" } + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - "@esbuild/win32-arm64@0.27.7": - resolution: - { - integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==, - } - engines: { node: ">=18" } + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - "@esbuild/win32-ia32@0.27.7": - resolution: - { - integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==, - } - engines: { node: ">=18" } + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - "@esbuild/win32-x64@0.27.7": - resolution: - { - integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==, - } - engines: { node: ">=18" } + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} cpu: [x64] os: [win32] - "@eslint-community/eslint-utils@4.9.1": - resolution: - { - integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - "@eslint-community/regexpp@4.12.2": - resolution: - { - integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, - } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - "@eslint/config-array@0.23.5": - resolution: - { - integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - "@eslint/config-helpers@0.6.0": - resolution: - { - integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + '@eslint/config-helpers@0.6.0': + resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - "@eslint/core@1.2.1": - resolution: - { - integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - "@eslint/js@10.0.1": - resolution: - { - integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + '@eslint/js@10.0.1': + resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} peerDependencies: eslint: ^10.0.0 peerDependenciesMeta: eslint: optional: true - "@eslint/object-schema@3.0.5": - resolution: - { - integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - "@eslint/plugin-kit@0.7.2": - resolution: - { - integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} - "@hono/node-server@1.19.14": - resolution: - { - integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==, - } - engines: { node: ">=18.14.1" } + '@hono/node-server@1.19.14': + resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} + engines: {node: '>=18.14.1'} peerDependencies: hono: ^4 - "@humanfs/core@0.19.2": - resolution: - { - integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==, - } - engines: { node: ">=18.18.0" } + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} - "@humanfs/node@0.16.8": - resolution: - { - integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==, - } - engines: { node: ">=18.18.0" } + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} - "@humanfs/types@0.15.0": - resolution: - { - integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==, - } - engines: { node: ">=18.18.0" } + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} - "@humanwhocodes/module-importer@1.0.1": - resolution: - { - integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, - } - engines: { node: ">=12.22" } + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} - "@humanwhocodes/retry@0.4.3": - resolution: - { - integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==, - } - engines: { node: ">=18.18" } + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} - "@jridgewell/sourcemap-codec@1.5.5": - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - "@modelcontextprotocol/sdk@1.29.0": - resolution: - { - integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==, - } - engines: { node: ">=18" } + '@modelcontextprotocol/sdk@1.29.0': + resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} + engines: {node: '>=18'} peerDependencies: - "@cfworker/json-schema": ^4.1.1 + '@cfworker/json-schema': ^4.1.1 zod: ^3.25 || ^4.0 peerDependenciesMeta: - "@cfworker/json-schema": + '@cfworker/json-schema': optional: true - "@rollup/rollup-android-arm-eabi@4.60.4": - resolution: - { - integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==, - } + '@rollup/rollup-android-arm-eabi@4.60.4': + resolution: {integrity: sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==} cpu: [arm] os: [android] - "@rollup/rollup-android-arm64@4.60.4": - resolution: - { - integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==, - } + '@rollup/rollup-android-arm64@4.60.4': + resolution: {integrity: sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==} cpu: [arm64] os: [android] - "@rollup/rollup-darwin-arm64@4.60.4": - resolution: - { - integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==, - } + '@rollup/rollup-darwin-arm64@4.60.4': + resolution: {integrity: sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==} cpu: [arm64] os: [darwin] - "@rollup/rollup-darwin-x64@4.60.4": - resolution: - { - integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==, - } + '@rollup/rollup-darwin-x64@4.60.4': + resolution: {integrity: sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==} cpu: [x64] os: [darwin] - "@rollup/rollup-freebsd-arm64@4.60.4": - resolution: - { - integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==, - } + '@rollup/rollup-freebsd-arm64@4.60.4': + resolution: {integrity: sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==} cpu: [arm64] os: [freebsd] - "@rollup/rollup-freebsd-x64@4.60.4": - resolution: - { - integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==, - } + '@rollup/rollup-freebsd-x64@4.60.4': + resolution: {integrity: sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==} cpu: [x64] os: [freebsd] - "@rollup/rollup-linux-arm-gnueabihf@4.60.4": - resolution: - { - integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==, - } + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': + resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} cpu: [arm] os: [linux] libc: [glibc] - "@rollup/rollup-linux-arm-musleabihf@4.60.4": - resolution: - { - integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==, - } + '@rollup/rollup-linux-arm-musleabihf@4.60.4': + resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} cpu: [arm] os: [linux] libc: [musl] - "@rollup/rollup-linux-arm64-gnu@4.60.4": - resolution: - { - integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==, - } + '@rollup/rollup-linux-arm64-gnu@4.60.4': + resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} cpu: [arm64] os: [linux] libc: [glibc] - "@rollup/rollup-linux-arm64-musl@4.60.4": - resolution: - { - integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==, - } + '@rollup/rollup-linux-arm64-musl@4.60.4': + resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} cpu: [arm64] os: [linux] libc: [musl] - "@rollup/rollup-linux-loong64-gnu@4.60.4": - resolution: - { - integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==, - } + '@rollup/rollup-linux-loong64-gnu@4.60.4': + resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} cpu: [loong64] os: [linux] libc: [glibc] - "@rollup/rollup-linux-loong64-musl@4.60.4": - resolution: - { - integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==, - } + '@rollup/rollup-linux-loong64-musl@4.60.4': + resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} cpu: [loong64] os: [linux] libc: [musl] - "@rollup/rollup-linux-ppc64-gnu@4.60.4": - resolution: - { - integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==, - } + '@rollup/rollup-linux-ppc64-gnu@4.60.4': + resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} cpu: [ppc64] os: [linux] libc: [glibc] - "@rollup/rollup-linux-ppc64-musl@4.60.4": - resolution: - { - integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==, - } + '@rollup/rollup-linux-ppc64-musl@4.60.4': + resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} cpu: [ppc64] os: [linux] libc: [musl] - "@rollup/rollup-linux-riscv64-gnu@4.60.4": - resolution: - { - integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==, - } + '@rollup/rollup-linux-riscv64-gnu@4.60.4': + resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} cpu: [riscv64] os: [linux] libc: [glibc] - "@rollup/rollup-linux-riscv64-musl@4.60.4": - resolution: - { - integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==, - } + '@rollup/rollup-linux-riscv64-musl@4.60.4': + resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} cpu: [riscv64] os: [linux] libc: [musl] - "@rollup/rollup-linux-s390x-gnu@4.60.4": - resolution: - { - integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==, - } + '@rollup/rollup-linux-s390x-gnu@4.60.4': + resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} cpu: [s390x] os: [linux] libc: [glibc] - "@rollup/rollup-linux-x64-gnu@4.60.4": - resolution: - { - integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==, - } + '@rollup/rollup-linux-x64-gnu@4.60.4': + resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} cpu: [x64] os: [linux] libc: [glibc] - "@rollup/rollup-linux-x64-musl@4.60.4": - resolution: - { - integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==, - } + '@rollup/rollup-linux-x64-musl@4.60.4': + resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} cpu: [x64] os: [linux] libc: [musl] - "@rollup/rollup-openbsd-x64@4.60.4": - resolution: - { - integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==, - } + '@rollup/rollup-openbsd-x64@4.60.4': + resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} cpu: [x64] os: [openbsd] - "@rollup/rollup-openharmony-arm64@4.60.4": - resolution: - { - integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==, - } + '@rollup/rollup-openharmony-arm64@4.60.4': + resolution: {integrity: sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==} cpu: [arm64] os: [openharmony] - "@rollup/rollup-win32-arm64-msvc@4.60.4": - resolution: - { - integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==, - } + '@rollup/rollup-win32-arm64-msvc@4.60.4': + resolution: {integrity: sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==} cpu: [arm64] os: [win32] - "@rollup/rollup-win32-ia32-msvc@4.60.4": - resolution: - { - integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==, - } + '@rollup/rollup-win32-ia32-msvc@4.60.4': + resolution: {integrity: sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==} cpu: [ia32] os: [win32] - "@rollup/rollup-win32-x64-gnu@4.60.4": - resolution: - { - integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==, - } + '@rollup/rollup-win32-x64-gnu@4.60.4': + resolution: {integrity: sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==} cpu: [x64] os: [win32] - "@rollup/rollup-win32-x64-msvc@4.60.4": - resolution: - { - integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==, - } + '@rollup/rollup-win32-x64-msvc@4.60.4': + resolution: {integrity: sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==} cpu: [x64] os: [win32] - "@types/chai@5.2.3": - resolution: - { - integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==, - } + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - "@types/deep-eql@4.0.2": - resolution: - { - integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==, - } + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - "@types/esrecurse@4.3.1": - resolution: - { - integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==, - } + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} - "@types/estree@1.0.8": - resolution: - { - integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, - } + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - "@types/estree@1.0.9": - resolution: - { - integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==, - } + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - "@types/json-schema@7.0.15": - resolution: - { - integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, - } + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - "@types/node@22.19.19": - resolution: - { - integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==, - } + '@types/node@22.19.19': + resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} - "@typescript-eslint/eslint-plugin@8.62.0": - resolution: - { - integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/eslint-plugin@8.62.0': + resolution: {integrity: sha512-o+mpz7EYiMzXoySXiKmzlabIvTVqUuK5yLrAedRPRDA0IpPFMUV1IXt6OqljIxX/kumN6EjUYp41Hqelh6p/Dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - "@typescript-eslint/parser": ^8.62.0 + '@typescript-eslint/parser': ^8.62.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/parser@8.62.0": - resolution: - { - integrity: sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/parser@8.62.0': + resolution: {integrity: sha512-dzHeT2gySzZtLDsuqxU9AkYgIsQoHAHtRBpOqM+Ofzx1Bwrd2RcCjQJ+6iQbsHOIR6NS33bF2W1k3blN1zLDrA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/project-service@8.62.0": - resolution: - { - integrity: sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/project-service@8.62.0': + resolution: {integrity: sha512-wexnCqiTg7BOGtbLDftYpRWlmLq4xfoMd7BKFR6Y75sZS3QmRKLdN3yWLhmIYgqMmP/OXWpj3H8odkb5nGURCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/scope-manager@8.62.0": - resolution: - { - integrity: sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/scope-manager@8.62.0': + resolution: {integrity: sha512-1lX38kNxXIRb8mEc3lbq5mdHq1Pf2+U0nFU65KfT18mtPxxl0fvjuEE92mHuXPuCtElJhOrddOpyMlM3Z0umEA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - "@typescript-eslint/tsconfig-utils@8.62.0": - resolution: - { - integrity: sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/tsconfig-utils@8.62.0': + resolution: {integrity: sha512-y2GAdB6ykaXUvuspbYnizQc4oDDz0Tz/Yc7iWrXf9mx8vm/L/0vLHCe0tS2boG96Zy+DivnVDQ9ZUEWoHqqx1g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/type-utils@8.62.0": - resolution: - { - integrity: sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/type-utils@8.62.0': + resolution: {integrity: sha512-+g5O3j0w2ldzC86Pv6fvbO/xhAonbJFIdf/MKQ1d30gndlsVzUOE83ldfSE15Qrl9fhFjK6AovHs5Wpp6vx86w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/types@8.62.0": - resolution: - { - integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/types@8.62.0': + resolution: {integrity: sha512-KvAclkktORPvM54TgLgA4z9HIV1M8zOgw9ZVNXl9f/8dLYfXYX1wkMXP7qmabpijQRV5bHJLOmoyGQbLMaUYeg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - "@typescript-eslint/typescript-estree@8.62.0": - resolution: - { - integrity: sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/typescript-estree@8.62.0': + resolution: {integrity: sha512-+hVbNxtW64pIcZWDPGbyaKF7vp2IBTVY5ma1blwwksrjdsbdqqEKvJWMGbBofei4F6Dovx1M0RJgoFeNu2279A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/utils@8.62.0": - resolution: - { - integrity: sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/utils@8.62.0': + resolution: {integrity: sha512-82r66fi9zYwZ+mTq3vKgwjbZ1PVk/DJzrXFLpG6RnBbdvH8TEGVHIs9H4d2drhkOzf0syZuD/OZvvlu6GDbP4g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/visitor-keys@8.62.0": - resolution: - { - integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/visitor-keys@8.62.0': + resolution: {integrity: sha512-CY3uyFSRbcQv3nnSv8S0+lDftMVz6P963PoRlxrV7ew/Md564g9ut60PYzdLM5qW4jFn93GBF+Soi90ISAN+GQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - "@vitest/expect@3.2.4": - resolution: - { - integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, - } + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - "@vitest/mocker@3.2.4": - resolution: - { - integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==, - } + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 @@ -1023,64 +764,37 @@ packages: vite: optional: true - "@vitest/pretty-format@3.2.4": - resolution: - { - integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, - } + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - "@vitest/runner@3.2.4": - resolution: - { - integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==, - } + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} - "@vitest/snapshot@3.2.4": - resolution: - { - integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==, - } + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} - "@vitest/spy@3.2.4": - resolution: - { - integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, - } + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - "@vitest/utils@3.2.4": - resolution: - { - integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, - } + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} accepts@2.0.0: - resolution: - { - integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} acorn-jsx@5.3.2: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn@8.17.0: - resolution: - { - integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==, - } - engines: { node: ">=0.4.0" } + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} hasBin: true ajv-formats@3.0.1: - resolution: - { - integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==, - } + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: ajv: ^8.0.0 peerDependenciesMeta: @@ -1088,485 +802,278 @@ packages: optional: true ajv@6.15.0: - resolution: - { - integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==, - } + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} ajv@8.20.0: - resolution: - { - integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==, - } + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} assertion-error@2.0.1: - resolution: - { - integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} balanced-match@4.0.4: - resolution: - { - integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==, - } - engines: { node: 18 || 20 || >=22 } + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} body-parser@2.3.0: - resolution: - { - integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} + engines: {node: '>=18'} boolbase@1.0.0: - resolution: - { - integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, - } + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} brace-expansion@5.0.6: - resolution: - { - integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==, - } - engines: { node: 18 || 20 || >=22 } + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} bytes@3.1.2: - resolution: - { - integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} cac@6.7.14: - resolution: - { - integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} call-bind-apply-helpers@1.0.2: - resolution: - { - integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} call-bound@1.0.4: - resolution: - { - integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} chai@5.3.3: - resolution: - { - integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} check-error@2.1.3: - resolution: - { - integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==, - } - engines: { node: ">= 16" } + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} cheerio-select@2.1.0: - resolution: - { - integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==, - } + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} cheerio@1.2.0: - resolution: - { - integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==, - } - engines: { node: ">=20.18.1" } + resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} + engines: {node: '>=20.18.1'} commander@12.1.0: - resolution: - { - integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} content-disposition@1.1.0: - resolution: - { - integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} content-type@1.0.5: - resolution: - { - integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} content-type@2.0.0: - resolution: - { - integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} + engines: {node: '>=18'} cookie-signature@1.2.2: - resolution: - { - integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==, - } - engines: { node: ">=6.6.0" } + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} cookie@0.7.2: - resolution: - { - integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} cors@2.8.6: - resolution: - { - integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} + engines: {node: '>= 0.10'} cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} css-select@5.2.2: - resolution: - { - integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, - } + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} css-what@6.2.2: - resolution: - { - integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: ">=6.0" } + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} peerDependencies: - supports-color: "*" + supports-color: '*' peerDependenciesMeta: supports-color: optional: true deep-eql@5.0.2: - resolution: - { - integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} deep-is@0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, - } + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} depd@2.0.0: - resolution: - { - integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} dom-serializer@2.0.0: - resolution: - { - integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, - } + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} domelementtype@2.3.0: - resolution: - { - integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, - } + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} domhandler@5.0.3: - resolution: - { - integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} domutils@3.2.2: - resolution: - { - integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, - } + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} dunder-proto@1.0.1: - resolution: - { - integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} ee-first@1.1.1: - resolution: - { - integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==, - } + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} encodeurl@2.0.0: - resolution: - { - integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} encoding-sniffer@0.2.1: - resolution: - { - integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==, - } + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} entities@4.5.0: - resolution: - { - integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, - } - engines: { node: ">=0.12" } + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} entities@6.0.1: - resolution: - { - integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, - } - engines: { node: ">=0.12" } + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} entities@7.0.1: - resolution: - { - integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==, - } - engines: { node: ">=0.12" } + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} es-module-lexer@1.7.0: - resolution: - { - integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==, - } + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} es-object-atoms@1.1.2: - resolution: - { - integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} esbuild@0.27.7: - resolution: - { - integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} hasBin: true escape-html@1.0.3: - resolution: - { - integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==, - } + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} eslint-config-prettier@10.1.8: - resolution: - { - integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, - } + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: - eslint: ">=7.0.0" + eslint: '>=7.0.0' eslint-scope@9.1.2: - resolution: - { - integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} eslint-visitor-keys@3.4.3: - resolution: - { - integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint-visitor-keys@5.0.1: - resolution: - { - integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} eslint@10.5.0: - resolution: - { - integrity: sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + resolution: {integrity: sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: - jiti: "*" + jiti: '*' peerDependenciesMeta: jiti: optional: true espree@11.2.0: - resolution: - { - integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} esquery@1.7.0: - resolution: - { - integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, - } - engines: { node: ">=0.10" } + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} estree-walker@3.0.3: - resolution: - { - integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, - } + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} etag@1.8.1: - resolution: - { - integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} eventsource-parser@3.1.0: - resolution: - { - integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==, - } - engines: { node: ">=18.0.0" } + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} + engines: {node: '>=18.0.0'} eventsource@3.0.7: - resolution: - { - integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==, - } - engines: { node: ">=18.0.0" } + resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==} + engines: {node: '>=18.0.0'} expect-type@1.3.0: - resolution: - { - integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} express-rate-limit@8.5.2: - resolution: - { - integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==, - } - engines: { node: ">= 16" } + resolution: {integrity: sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==} + engines: {node: '>= 16'} peerDependencies: - express: ">= 4.11" + express: '>= 4.11' express@5.2.1: - resolution: - { - integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==, - } - engines: { node: ">= 18" } + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} + engines: {node: '>= 18'} fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} fast-json-stable-stringify@2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, - } + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, - } + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fast-uri@3.1.2: - resolution: - { - integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==, - } + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fdir@6.5.0: - resolution: - { - integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -1574,828 +1081,471 @@ packages: optional: true file-entry-cache@8.0.0: - resolution: - { - integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==, - } - engines: { node: ">=16.0.0" } + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} finalhandler@2.1.1: - resolution: - { - integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==, - } - engines: { node: ">= 18.0.0" } + resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} + engines: {node: '>= 18.0.0'} find-up@5.0.0: - resolution: - { - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} flat-cache@4.0.1: - resolution: - { - integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flatted@3.4.2: - resolution: - { - integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==, - } + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} forwarded@0.2.0: - resolution: - { - integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} fresh@2.0.0: - resolution: - { - integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} fsevents@2.3.3: - resolution: - { - integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, - } + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} get-intrinsic@1.3.0: - resolution: - { - integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} get-proto@1.0.1: - resolution: - { - integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} glob-parent@6.0.2: - resolution: - { - integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} gopd@1.2.0: - resolution: - { - integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} has-symbols@1.1.0: - resolution: - { - integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} hasown@2.0.4: - resolution: - { - integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} hono@4.12.27: - resolution: - { - integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==, - } - engines: { node: ">=16.9.0" } + resolution: {integrity: sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==} + engines: {node: '>=16.9.0'} htmlparser2@10.1.0: - resolution: - { - integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==, - } + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} http-errors@2.0.1: - resolution: - { - integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} iconv-lite@0.6.3: - resolution: - { - integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} iconv-lite@0.7.2: - resolution: - { - integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} ignore@5.3.2: - resolution: - { - integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} ignore@7.0.5: - resolution: - { - integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} imurmurhash@0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: ">=0.8.19" } + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} ip-address@10.2.0: - resolution: - { - integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==, - } - engines: { node: ">= 12" } + resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} + engines: {node: '>= 12'} ipaddr.js@1.9.1: - resolution: - { - integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} is-promise@4.0.0: - resolution: - { - integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==, - } + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} jose@6.2.3: - resolution: - { - integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==, - } + resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} js-tokens@9.0.1: - resolution: - { - integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==, - } + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} json-buffer@3.0.1: - resolution: - { - integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, - } + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-schema-traverse@0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, - } + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-schema-traverse@1.0.0: - resolution: - { - integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==, - } + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} json-schema-typed@8.0.2: - resolution: - { - integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==, - } + resolution: {integrity: sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==} json-stable-stringify-without-jsonify@1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, - } + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, - } + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} levn@0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} locate-path@6.0.0: - resolution: - { - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} loupe@3.2.1: - resolution: - { - integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==, - } + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} magic-string@0.30.21: - resolution: - { - integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, - } + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} math-intrinsics@1.1.0: - resolution: - { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} media-typer@1.1.0: - resolution: - { - integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} merge-descriptors@2.0.0: - resolution: - { - integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} - mime-db@1.54.0: - resolution: - { - integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==, - } - engines: { node: ">= 0.6" } + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} mime-types@3.0.2: - resolution: - { - integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} minimatch@10.2.5: - resolution: - { - integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==, - } - engines: { node: 18 || 20 || >=22 } + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} nanoid@3.3.12: - resolution: - { - integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==, - } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} negotiator@1.0.0: - resolution: - { - integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} nth-check@2.1.1: - resolution: - { - integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, - } + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} object-assign@4.1.1: - resolution: - { - integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} object-inspect@1.13.4: - resolution: - { - integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} on-finished@2.4.1: - resolution: - { - integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} optionator@0.9.4: - resolution: - { - integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} p-limit@3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} p-locate@5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} parse5-htmlparser2-tree-adapter@7.1.0: - resolution: - { - integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==, - } + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} parse5-parser-stream@7.1.2: - resolution: - { - integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==, - } + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} parse5@7.3.0: - resolution: - { - integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, - } + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} parseurl@1.3.3: - resolution: - { - integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} path-exists@4.0.0: - resolution: - { - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} path-to-regexp@8.4.2: - resolution: - { - integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==, - } + resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} pathe@2.0.3: - resolution: - { - integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, - } + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pathval@2.0.1: - resolution: - { - integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, - } - engines: { node: ">= 14.16" } + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} picocolors@1.1.1: - resolution: - { - integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, - } + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@4.0.4: - resolution: - { - integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} pkce-challenge@5.0.1: - resolution: - { - integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==, - } - engines: { node: ">=16.20.0" } + resolution: {integrity: sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==} + engines: {node: '>=16.20.0'} postcss@8.5.14: - resolution: - { - integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==, - } - engines: { node: ^10 || ^12 || >=14 } + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} + engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} prettier@3.8.4: - resolution: - { - integrity: sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==} + engines: {node: '>=14'} hasBin: true proxy-addr@2.0.7: - resolution: - { - integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} qs@6.15.2: - resolution: - { - integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==, - } - engines: { node: ">=0.6" } + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} range-parser@1.2.1: - resolution: - { - integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} raw-body@3.0.2: - resolution: - { - integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} + engines: {node: '>= 0.10'} require-from-string@2.0.2: - resolution: - { - integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} rollup@4.60.4: - resolution: - { - integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==, - } - engines: { node: ">=18.0.0", npm: ">=8.0.0" } + resolution: {integrity: sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true router@2.2.0: - resolution: - { - integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==, - } - engines: { node: ">= 18" } + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} safer-buffer@2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} semver@7.8.5: - resolution: - { - integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} hasBin: true send@1.2.1: - resolution: - { - integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==, - } - engines: { node: ">= 18" } + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} + engines: {node: '>= 18'} serve-static@2.2.1: - resolution: - { - integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==, - } - engines: { node: ">= 18" } + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} + engines: {node: '>= 18'} setprototypeof@1.2.0: - resolution: - { - integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==, - } + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} side-channel-list@1.0.1: - resolution: - { - integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} side-channel-map@1.0.1: - resolution: - { - integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} side-channel-weakmap@1.0.2: - resolution: - { - integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} side-channel@1.1.1: - resolution: - { - integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} siginfo@2.0.0: - resolution: - { - integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, - } + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} source-map-js@1.2.1: - resolution: - { - integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} stackback@0.0.2: - resolution: - { - integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, - } + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} statuses@2.0.2: - resolution: - { - integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} std-env@3.10.0: - resolution: - { - integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==, - } + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} strip-literal@3.1.0: - resolution: - { - integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==, - } + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} tinybench@2.9.0: - resolution: - { - integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, - } + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} tinyexec@0.3.2: - resolution: - { - integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==, - } + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} tinyglobby@0.2.16: - resolution: - { - integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} tinypool@1.1.1: - resolution: - { - integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==, - } - engines: { node: ^18.0.0 || >=20.0.0 } + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@2.0.0: - resolution: - { - integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} tinyspy@4.0.4: - resolution: - { - integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} toidentifier@1.0.1: - resolution: - { - integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, - } - engines: { node: ">=0.6" } + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} ts-api-utils@2.5.0: - resolution: - { - integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==, - } - engines: { node: ">=18.12" } + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} peerDependencies: - typescript: ">=4.8.4" + typescript: '>=4.8.4' type-check@0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} type-is@2.1.0: - resolution: - { - integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==, - } - engines: { node: ">= 18" } + resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} + engines: {node: '>= 18'} typescript-eslint@8.62.0: - resolution: - { - integrity: sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-8QxXi+ZACKX0kaqO4gY8kn0RSD9gFfaHDWwjqtEN48aWCBkX4MJaufWN+c3BzlrXLOxfywDL8CaoqUwcRq4j4Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: ">=14.17" } + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true undici-types@6.21.0: - resolution: - { - integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==, - } + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} undici@7.25.0: - resolution: - { - integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==, - } - engines: { node: ">=20.18.1" } + resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + engines: {node: '>=20.18.1'} unpipe@1.0.0: - resolution: - { - integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} vary@1.1.2: - resolution: - { - integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} vite-node@3.2.4: - resolution: - { - integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==, - } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true vite@7.3.3: - resolution: - { - integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - "@types/node": ^20.19.0 || >=22.12.0 - jiti: ">=1.21.0" + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' less: ^4.0.0 lightningcss: ^1.21.0 sass: ^1.70.0 sass-embedded: ^1.70.0 - stylus: ">=0.54.8" + stylus: '>=0.54.8' sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 peerDependenciesMeta: - "@types/node": + '@types/node': optional: true jiti: optional: true @@ -2419,30 +1569,27 @@ packages: optional: true vitest@3.2.4: - resolution: - { - integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==, - } - engines: { node: ^18.0.0 || ^20.0.0 || >=22.0.0 } + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - "@vitest/browser": 3.2.4 - "@vitest/ui": 3.2.4 - happy-dom: "*" - jsdom: "*" + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' peerDependenciesMeta: - "@edge-runtime/vm": + '@edge-runtime/vm': optional: true - "@types/debug": + '@types/debug': optional: true - "@types/node": + '@types/node': optional: true - "@vitest/browser": + '@vitest/browser': optional: true - "@vitest/ui": + '@vitest/ui': optional: true happy-dom: optional: true @@ -2450,208 +1597,182 @@ packages: optional: true whatwg-encoding@3.1.1: - resolution: - { - integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: - resolution: - { - integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} hasBin: true why-is-node-running@2.3.0: - resolution: - { - integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} hasBin: true word-wrap@1.2.5: - resolution: - { - integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} yocto-queue@0.1.0: - resolution: - { - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} zod-to-json-schema@3.25.2: - resolution: - { - integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==, - } + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} peerDependencies: zod: ^3.25.28 || ^4 zod@4.4.3: - resolution: - { - integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==, - } + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} snapshots: - "@esbuild/aix-ppc64@0.27.7": + + '@esbuild/aix-ppc64@0.27.7': optional: true - "@esbuild/android-arm64@0.27.7": + '@esbuild/android-arm64@0.27.7': optional: true - "@esbuild/android-arm@0.27.7": + '@esbuild/android-arm@0.27.7': optional: true - "@esbuild/android-x64@0.27.7": + '@esbuild/android-x64@0.27.7': optional: true - "@esbuild/darwin-arm64@0.27.7": + '@esbuild/darwin-arm64@0.27.7': optional: true - "@esbuild/darwin-x64@0.27.7": + '@esbuild/darwin-x64@0.27.7': optional: true - "@esbuild/freebsd-arm64@0.27.7": + '@esbuild/freebsd-arm64@0.27.7': optional: true - "@esbuild/freebsd-x64@0.27.7": + '@esbuild/freebsd-x64@0.27.7': optional: true - "@esbuild/linux-arm64@0.27.7": + '@esbuild/linux-arm64@0.27.7': optional: true - "@esbuild/linux-arm@0.27.7": + '@esbuild/linux-arm@0.27.7': optional: true - "@esbuild/linux-ia32@0.27.7": + '@esbuild/linux-ia32@0.27.7': optional: true - "@esbuild/linux-loong64@0.27.7": + '@esbuild/linux-loong64@0.27.7': optional: true - "@esbuild/linux-mips64el@0.27.7": + '@esbuild/linux-mips64el@0.27.7': optional: true - "@esbuild/linux-ppc64@0.27.7": + '@esbuild/linux-ppc64@0.27.7': optional: true - "@esbuild/linux-riscv64@0.27.7": + '@esbuild/linux-riscv64@0.27.7': optional: true - "@esbuild/linux-s390x@0.27.7": + '@esbuild/linux-s390x@0.27.7': optional: true - "@esbuild/linux-x64@0.27.7": + '@esbuild/linux-x64@0.27.7': optional: true - "@esbuild/netbsd-arm64@0.27.7": + '@esbuild/netbsd-arm64@0.27.7': optional: true - "@esbuild/netbsd-x64@0.27.7": + '@esbuild/netbsd-x64@0.27.7': optional: true - "@esbuild/openbsd-arm64@0.27.7": + '@esbuild/openbsd-arm64@0.27.7': optional: true - "@esbuild/openbsd-x64@0.27.7": + '@esbuild/openbsd-x64@0.27.7': optional: true - "@esbuild/openharmony-arm64@0.27.7": + '@esbuild/openharmony-arm64@0.27.7': optional: true - "@esbuild/sunos-x64@0.27.7": + '@esbuild/sunos-x64@0.27.7': optional: true - "@esbuild/win32-arm64@0.27.7": + '@esbuild/win32-arm64@0.27.7': optional: true - "@esbuild/win32-ia32@0.27.7": + '@esbuild/win32-ia32@0.27.7': optional: true - "@esbuild/win32-x64@0.27.7": + '@esbuild/win32-x64@0.27.7': optional: true - "@eslint-community/eslint-utils@4.9.1(eslint@10.5.0)": + '@eslint-community/eslint-utils@4.9.1(eslint@10.5.0)': dependencies: eslint: 10.5.0 eslint-visitor-keys: 3.4.3 - "@eslint-community/regexpp@4.12.2": {} + '@eslint-community/regexpp@4.12.2': {} - "@eslint/config-array@0.23.5": + '@eslint/config-array@0.23.5': dependencies: - "@eslint/object-schema": 3.0.5 + '@eslint/object-schema': 3.0.5 debug: 4.4.3 minimatch: 10.2.5 transitivePeerDependencies: - supports-color - "@eslint/config-helpers@0.6.0": + '@eslint/config-helpers@0.6.0': dependencies: - "@eslint/core": 1.2.1 + '@eslint/core': 1.2.1 - "@eslint/core@1.2.1": + '@eslint/core@1.2.1': dependencies: - "@types/json-schema": 7.0.15 + '@types/json-schema': 7.0.15 - "@eslint/js@10.0.1(eslint@10.5.0)": + '@eslint/js@10.0.1(eslint@10.5.0)': optionalDependencies: eslint: 10.5.0 - "@eslint/object-schema@3.0.5": {} + '@eslint/object-schema@3.0.5': {} - "@eslint/plugin-kit@0.7.2": + '@eslint/plugin-kit@0.7.2': dependencies: - "@eslint/core": 1.2.1 + '@eslint/core': 1.2.1 levn: 0.4.1 - "@hono/node-server@1.19.14(hono@4.12.27)": + '@hono/node-server@1.19.14(hono@4.12.27)': dependencies: hono: 4.12.27 - "@humanfs/core@0.19.2": + '@humanfs/core@0.19.2': dependencies: - "@humanfs/types": 0.15.0 + '@humanfs/types': 0.15.0 - "@humanfs/node@0.16.8": + '@humanfs/node@0.16.8': dependencies: - "@humanfs/core": 0.19.2 - "@humanfs/types": 0.15.0 - "@humanwhocodes/retry": 0.4.3 + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 - "@humanfs/types@0.15.0": {} + '@humanfs/types@0.15.0': {} - "@humanwhocodes/module-importer@1.0.1": {} + '@humanwhocodes/module-importer@1.0.1': {} - "@humanwhocodes/retry@0.4.3": {} + '@humanwhocodes/retry@0.4.3': {} - "@jridgewell/sourcemap-codec@1.5.5": {} + '@jridgewell/sourcemap-codec@1.5.5': {} - "@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)": + '@modelcontextprotocol/sdk@1.29.0(zod@4.4.3)': dependencies: - "@hono/node-server": 1.19.14(hono@4.12.27) + '@hono/node-server': 1.19.14(hono@4.12.27) ajv: 8.20.0 ajv-formats: 3.0.1(ajv@8.20.0) content-type: 1.0.5 @@ -2671,108 +1792,108 @@ snapshots: transitivePeerDependencies: - supports-color - "@rollup/rollup-android-arm-eabi@4.60.4": + '@rollup/rollup-android-arm-eabi@4.60.4': optional: true - "@rollup/rollup-android-arm64@4.60.4": + '@rollup/rollup-android-arm64@4.60.4': optional: true - "@rollup/rollup-darwin-arm64@4.60.4": + '@rollup/rollup-darwin-arm64@4.60.4': optional: true - "@rollup/rollup-darwin-x64@4.60.4": + '@rollup/rollup-darwin-x64@4.60.4': optional: true - "@rollup/rollup-freebsd-arm64@4.60.4": + '@rollup/rollup-freebsd-arm64@4.60.4': optional: true - "@rollup/rollup-freebsd-x64@4.60.4": + '@rollup/rollup-freebsd-x64@4.60.4': optional: true - "@rollup/rollup-linux-arm-gnueabihf@4.60.4": + '@rollup/rollup-linux-arm-gnueabihf@4.60.4': optional: true - "@rollup/rollup-linux-arm-musleabihf@4.60.4": + '@rollup/rollup-linux-arm-musleabihf@4.60.4': optional: true - "@rollup/rollup-linux-arm64-gnu@4.60.4": + '@rollup/rollup-linux-arm64-gnu@4.60.4': optional: true - "@rollup/rollup-linux-arm64-musl@4.60.4": + '@rollup/rollup-linux-arm64-musl@4.60.4': optional: true - "@rollup/rollup-linux-loong64-gnu@4.60.4": + '@rollup/rollup-linux-loong64-gnu@4.60.4': optional: true - "@rollup/rollup-linux-loong64-musl@4.60.4": + '@rollup/rollup-linux-loong64-musl@4.60.4': optional: true - "@rollup/rollup-linux-ppc64-gnu@4.60.4": + '@rollup/rollup-linux-ppc64-gnu@4.60.4': optional: true - "@rollup/rollup-linux-ppc64-musl@4.60.4": + '@rollup/rollup-linux-ppc64-musl@4.60.4': optional: true - "@rollup/rollup-linux-riscv64-gnu@4.60.4": + '@rollup/rollup-linux-riscv64-gnu@4.60.4': optional: true - "@rollup/rollup-linux-riscv64-musl@4.60.4": + '@rollup/rollup-linux-riscv64-musl@4.60.4': optional: true - "@rollup/rollup-linux-s390x-gnu@4.60.4": + '@rollup/rollup-linux-s390x-gnu@4.60.4': optional: true - "@rollup/rollup-linux-x64-gnu@4.60.4": + '@rollup/rollup-linux-x64-gnu@4.60.4': optional: true - "@rollup/rollup-linux-x64-musl@4.60.4": + '@rollup/rollup-linux-x64-musl@4.60.4': optional: true - "@rollup/rollup-openbsd-x64@4.60.4": + '@rollup/rollup-openbsd-x64@4.60.4': optional: true - "@rollup/rollup-openharmony-arm64@4.60.4": + '@rollup/rollup-openharmony-arm64@4.60.4': optional: true - "@rollup/rollup-win32-arm64-msvc@4.60.4": + '@rollup/rollup-win32-arm64-msvc@4.60.4': optional: true - "@rollup/rollup-win32-ia32-msvc@4.60.4": + '@rollup/rollup-win32-ia32-msvc@4.60.4': optional: true - "@rollup/rollup-win32-x64-gnu@4.60.4": + '@rollup/rollup-win32-x64-gnu@4.60.4': optional: true - "@rollup/rollup-win32-x64-msvc@4.60.4": + '@rollup/rollup-win32-x64-msvc@4.60.4': optional: true - "@types/chai@5.2.3": + '@types/chai@5.2.3': dependencies: - "@types/deep-eql": 4.0.2 + '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - "@types/deep-eql@4.0.2": {} + '@types/deep-eql@4.0.2': {} - "@types/esrecurse@4.3.1": {} + '@types/esrecurse@4.3.1': {} - "@types/estree@1.0.8": {} + '@types/estree@1.0.8': {} - "@types/estree@1.0.9": {} + '@types/estree@1.0.9': {} - "@types/json-schema@7.0.15": {} + '@types/json-schema@7.0.15': {} - "@types/node@22.19.19": + '@types/node@22.19.19': dependencies: undici-types: 6.21.0 - "@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@5.9.3))(eslint@10.5.0)(typescript@5.9.3)": + '@typescript-eslint/eslint-plugin@8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@5.9.3))(eslint@10.5.0)(typescript@5.9.3)': dependencies: - "@eslint-community/regexpp": 4.12.2 - "@typescript-eslint/parser": 8.62.0(eslint@10.5.0)(typescript@5.9.3) - "@typescript-eslint/scope-manager": 8.62.0 - "@typescript-eslint/type-utils": 8.62.0(eslint@10.5.0)(typescript@5.9.3) - "@typescript-eslint/utils": 8.62.0(eslint@10.5.0)(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.62.0 + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.62.0(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/type-utils': 8.62.0(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.62.0(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.62.0 eslint: 10.5.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -2781,41 +1902,41 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@5.9.3)": + '@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@5.9.3)': dependencies: - "@typescript-eslint/scope-manager": 8.62.0 - "@typescript-eslint/types": 8.62.0 - "@typescript-eslint/typescript-estree": 8.62.0(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.62.0 + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.62.0 debug: 4.4.3 eslint: 10.5.0 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/project-service@8.62.0(typescript@5.9.3)": + '@typescript-eslint/project-service@8.62.0(typescript@5.9.3)': dependencies: - "@typescript-eslint/tsconfig-utils": 8.62.0(typescript@5.9.3) - "@typescript-eslint/types": 8.62.0 + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@5.9.3) + '@typescript-eslint/types': 8.62.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/scope-manager@8.62.0": + '@typescript-eslint/scope-manager@8.62.0': dependencies: - "@typescript-eslint/types": 8.62.0 - "@typescript-eslint/visitor-keys": 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/visitor-keys': 8.62.0 - "@typescript-eslint/tsconfig-utils@8.62.0(typescript@5.9.3)": + '@typescript-eslint/tsconfig-utils@8.62.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - "@typescript-eslint/type-utils@8.62.0(eslint@10.5.0)(typescript@5.9.3)": + '@typescript-eslint/type-utils@8.62.0(eslint@10.5.0)(typescript@5.9.3)': dependencies: - "@typescript-eslint/types": 8.62.0 - "@typescript-eslint/typescript-estree": 8.62.0(typescript@5.9.3) - "@typescript-eslint/utils": 8.62.0(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.62.0(eslint@10.5.0)(typescript@5.9.3) debug: 4.4.3 eslint: 10.5.0 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -2823,14 +1944,14 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/types@8.62.0": {} + '@typescript-eslint/types@8.62.0': {} - "@typescript-eslint/typescript-estree@8.62.0(typescript@5.9.3)": + '@typescript-eslint/typescript-estree@8.62.0(typescript@5.9.3)': dependencies: - "@typescript-eslint/project-service": 8.62.0(typescript@5.9.3) - "@typescript-eslint/tsconfig-utils": 8.62.0(typescript@5.9.3) - "@typescript-eslint/types": 8.62.0 - "@typescript-eslint/visitor-keys": 8.62.0 + '@typescript-eslint/project-service': 8.62.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.62.0(typescript@5.9.3) + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/visitor-keys': 8.62.0 debug: 4.4.3 minimatch: 10.2.5 semver: 7.8.5 @@ -2840,61 +1961,61 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/utils@8.62.0(eslint@10.5.0)(typescript@5.9.3)": + '@typescript-eslint/utils@8.62.0(eslint@10.5.0)(typescript@5.9.3)': dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.5.0) - "@typescript-eslint/scope-manager": 8.62.0 - "@typescript-eslint/types": 8.62.0 - "@typescript-eslint/typescript-estree": 8.62.0(typescript@5.9.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0) + '@typescript-eslint/scope-manager': 8.62.0 + '@typescript-eslint/types': 8.62.0 + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) eslint: 10.5.0 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/visitor-keys@8.62.0": + '@typescript-eslint/visitor-keys@8.62.0': dependencies: - "@typescript-eslint/types": 8.62.0 + '@typescript-eslint/types': 8.62.0 eslint-visitor-keys: 5.0.1 - "@vitest/expect@3.2.4": + '@vitest/expect@3.2.4': dependencies: - "@types/chai": 5.2.3 - "@vitest/spy": 3.2.4 - "@vitest/utils": 3.2.4 + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.3.3 tinyrainbow: 2.0.0 - "@vitest/mocker@3.2.4(vite@7.3.3(@types/node@22.19.19))": + '@vitest/mocker@3.2.4(vite@7.3.3(@types/node@22.19.19))': dependencies: - "@vitest/spy": 3.2.4 + '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 7.3.3(@types/node@22.19.19) - "@vitest/pretty-format@3.2.4": + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 - "@vitest/runner@3.2.4": + '@vitest/runner@3.2.4': dependencies: - "@vitest/utils": 3.2.4 + '@vitest/utils': 3.2.4 pathe: 2.0.3 strip-literal: 3.1.0 - "@vitest/snapshot@3.2.4": + '@vitest/snapshot@3.2.4': dependencies: - "@vitest/pretty-format": 3.2.4 + '@vitest/pretty-format': 3.2.4 magic-string: 0.30.21 pathe: 2.0.3 - "@vitest/spy@3.2.4": + '@vitest/spy@3.2.4': dependencies: tinyspy: 4.0.4 - "@vitest/utils@3.2.4": + '@vitest/utils@3.2.4': dependencies: - "@vitest/pretty-format": 3.2.4 + '@vitest/pretty-format': 3.2.4 loupe: 3.2.1 tinyrainbow: 2.0.0 @@ -3092,32 +2213,32 @@ snapshots: esbuild@0.27.7: optionalDependencies: - "@esbuild/aix-ppc64": 0.27.7 - "@esbuild/android-arm": 0.27.7 - "@esbuild/android-arm64": 0.27.7 - "@esbuild/android-x64": 0.27.7 - "@esbuild/darwin-arm64": 0.27.7 - "@esbuild/darwin-x64": 0.27.7 - "@esbuild/freebsd-arm64": 0.27.7 - "@esbuild/freebsd-x64": 0.27.7 - "@esbuild/linux-arm": 0.27.7 - "@esbuild/linux-arm64": 0.27.7 - "@esbuild/linux-ia32": 0.27.7 - "@esbuild/linux-loong64": 0.27.7 - "@esbuild/linux-mips64el": 0.27.7 - "@esbuild/linux-ppc64": 0.27.7 - "@esbuild/linux-riscv64": 0.27.7 - "@esbuild/linux-s390x": 0.27.7 - "@esbuild/linux-x64": 0.27.7 - "@esbuild/netbsd-arm64": 0.27.7 - "@esbuild/netbsd-x64": 0.27.7 - "@esbuild/openbsd-arm64": 0.27.7 - "@esbuild/openbsd-x64": 0.27.7 - "@esbuild/openharmony-arm64": 0.27.7 - "@esbuild/sunos-x64": 0.27.7 - "@esbuild/win32-arm64": 0.27.7 - "@esbuild/win32-ia32": 0.27.7 - "@esbuild/win32-x64": 0.27.7 + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 escape-html@1.0.3: {} @@ -3129,8 +2250,8 @@ snapshots: eslint-scope@9.1.2: dependencies: - "@types/esrecurse": 4.3.1 - "@types/estree": 1.0.9 + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 esrecurse: 4.3.0 estraverse: 5.3.0 @@ -3140,16 +2261,16 @@ snapshots: eslint@10.5.0: dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@10.5.0) - "@eslint-community/regexpp": 4.12.2 - "@eslint/config-array": 0.23.5 - "@eslint/config-helpers": 0.6.0 - "@eslint/core": 1.2.1 - "@eslint/plugin-kit": 0.7.2 - "@humanfs/node": 0.16.8 - "@humanwhocodes/module-importer": 1.0.1 - "@humanwhocodes/retry": 0.4.3 - "@types/estree": 1.0.9 + '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.6.0 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.2 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 ajv: 6.15.0 cross-spawn: 7.0.6 debug: 4.4.3 @@ -3191,7 +2312,7 @@ snapshots: estree-walker@3.0.3: dependencies: - "@types/estree": 1.0.9 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -3399,7 +2520,7 @@ snapshots: magic-string@0.30.21: dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 + '@jridgewell/sourcemap-codec': 1.5.5 math-intrinsics@1.1.0: {} @@ -3523,33 +2644,33 @@ snapshots: rollup@4.60.4: dependencies: - "@types/estree": 1.0.8 + '@types/estree': 1.0.8 optionalDependencies: - "@rollup/rollup-android-arm-eabi": 4.60.4 - "@rollup/rollup-android-arm64": 4.60.4 - "@rollup/rollup-darwin-arm64": 4.60.4 - "@rollup/rollup-darwin-x64": 4.60.4 - "@rollup/rollup-freebsd-arm64": 4.60.4 - "@rollup/rollup-freebsd-x64": 4.60.4 - "@rollup/rollup-linux-arm-gnueabihf": 4.60.4 - "@rollup/rollup-linux-arm-musleabihf": 4.60.4 - "@rollup/rollup-linux-arm64-gnu": 4.60.4 - "@rollup/rollup-linux-arm64-musl": 4.60.4 - "@rollup/rollup-linux-loong64-gnu": 4.60.4 - "@rollup/rollup-linux-loong64-musl": 4.60.4 - "@rollup/rollup-linux-ppc64-gnu": 4.60.4 - "@rollup/rollup-linux-ppc64-musl": 4.60.4 - "@rollup/rollup-linux-riscv64-gnu": 4.60.4 - "@rollup/rollup-linux-riscv64-musl": 4.60.4 - "@rollup/rollup-linux-s390x-gnu": 4.60.4 - "@rollup/rollup-linux-x64-gnu": 4.60.4 - "@rollup/rollup-linux-x64-musl": 4.60.4 - "@rollup/rollup-openbsd-x64": 4.60.4 - "@rollup/rollup-openharmony-arm64": 4.60.4 - "@rollup/rollup-win32-arm64-msvc": 4.60.4 - "@rollup/rollup-win32-ia32-msvc": 4.60.4 - "@rollup/rollup-win32-x64-gnu": 4.60.4 - "@rollup/rollup-win32-x64-msvc": 4.60.4 + '@rollup/rollup-android-arm-eabi': 4.60.4 + '@rollup/rollup-android-arm64': 4.60.4 + '@rollup/rollup-darwin-arm64': 4.60.4 + '@rollup/rollup-darwin-x64': 4.60.4 + '@rollup/rollup-freebsd-arm64': 4.60.4 + '@rollup/rollup-freebsd-x64': 4.60.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.4 + '@rollup/rollup-linux-arm-musleabihf': 4.60.4 + '@rollup/rollup-linux-arm64-gnu': 4.60.4 + '@rollup/rollup-linux-arm64-musl': 4.60.4 + '@rollup/rollup-linux-loong64-gnu': 4.60.4 + '@rollup/rollup-linux-loong64-musl': 4.60.4 + '@rollup/rollup-linux-ppc64-gnu': 4.60.4 + '@rollup/rollup-linux-ppc64-musl': 4.60.4 + '@rollup/rollup-linux-riscv64-gnu': 4.60.4 + '@rollup/rollup-linux-riscv64-musl': 4.60.4 + '@rollup/rollup-linux-s390x-gnu': 4.60.4 + '@rollup/rollup-linux-x64-gnu': 4.60.4 + '@rollup/rollup-linux-x64-musl': 4.60.4 + '@rollup/rollup-openbsd-x64': 4.60.4 + '@rollup/rollup-openharmony-arm64': 4.60.4 + '@rollup/rollup-win32-arm64-msvc': 4.60.4 + '@rollup/rollup-win32-ia32-msvc': 4.60.4 + '@rollup/rollup-win32-x64-gnu': 4.60.4 + '@rollup/rollup-win32-x64-msvc': 4.60.4 fsevents: 2.3.3 router@2.2.0: @@ -3674,10 +2795,10 @@ snapshots: typescript-eslint@8.62.0(eslint@10.5.0)(typescript@5.9.3): dependencies: - "@typescript-eslint/eslint-plugin": 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@5.9.3))(eslint@10.5.0)(typescript@5.9.3) - "@typescript-eslint/parser": 8.62.0(eslint@10.5.0)(typescript@5.9.3) - "@typescript-eslint/typescript-estree": 8.62.0(typescript@5.9.3) - "@typescript-eslint/utils": 8.62.0(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.62.0(@typescript-eslint/parser@8.62.0(eslint@10.5.0)(typescript@5.9.3))(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/parser': 8.62.0(eslint@10.5.0)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.62.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.62.0(eslint@10.5.0)(typescript@5.9.3) eslint: 10.5.0 typescript: 5.9.3 transitivePeerDependencies: @@ -3705,7 +2826,7 @@ snapshots: pathe: 2.0.3 vite: 7.3.3(@types/node@22.19.19) transitivePeerDependencies: - - "@types/node" + - '@types/node' - jiti - less - lightningcss @@ -3727,19 +2848,19 @@ snapshots: rollup: 4.60.4 tinyglobby: 0.2.16 optionalDependencies: - "@types/node": 22.19.19 + '@types/node': 22.19.19 fsevents: 2.3.3 vitest@3.2.4(@types/node@22.19.19): dependencies: - "@types/chai": 5.2.3 - "@vitest/expect": 3.2.4 - "@vitest/mocker": 3.2.4(vite@7.3.3(@types/node@22.19.19)) - "@vitest/pretty-format": 3.2.4 - "@vitest/runner": 3.2.4 - "@vitest/snapshot": 3.2.4 - "@vitest/spy": 3.2.4 - "@vitest/utils": 3.2.4 + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.3.3(@types/node@22.19.19)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.3.3 debug: 4.4.3 expect-type: 1.3.0 @@ -3756,7 +2877,7 @@ snapshots: vite-node: 3.2.4(@types/node@22.19.19) why-is-node-running: 2.3.0 optionalDependencies: - "@types/node": 22.19.19 + '@types/node': 22.19.19 transitivePeerDependencies: - jiti - less From deb95d983ba08b92348d9aef1ef9e01927d1a3fa Mon Sep 17 00:00:00 2001 From: Zou Zhao Date: Sun, 20 Sep 2026 06:18:05 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix(fetcher):=20=E4=BF=AE=E5=A4=8D=E6=90=9C?= =?UTF-8?q?=E7=8B=97=E6=90=9C=E7=B4=A2=E9=93=BE=E8=B7=AF=E7=9A=84=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E4=B8=8E=E7=9C=9F=E5=AE=9E=E9=93=BE=E6=8E=A5=E8=BF=98?= =?UTF-8?q?=E5=8E=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/commands/search.ts | 15 +- src/lib/__test__/fetcher.test.ts | 28 +- src/lib/fetcher.ts | 61 ++- src/lib/types.ts | 16 + src/tests/fixtures/sogou-redirect-real.html | 24 ++ src/tests/fixtures/sogou-search-real.html | 430 ++++++++++++++++++++ 6 files changed, 552 insertions(+), 22 deletions(-) create mode 100644 src/tests/fixtures/sogou-redirect-real.html create mode 100644 src/tests/fixtures/sogou-search-real.html diff --git a/src/commands/search.ts b/src/commands/search.ts index 1e2fca7..286a35b 100644 --- a/src/commands/search.ts +++ b/src/commands/search.ts @@ -1,5 +1,5 @@ import { Command } from "commander" -import { searchSogou, searchSogouAll } from "../lib/fetcher.js" +import { searchSogou, searchSogouAll, resolveResultsRealUrls } from "../lib/fetcher.js" export function setupSearchCommand(program: Command): void { program @@ -8,11 +8,18 @@ export function setupSearchCommand(program: Command): void { .option("-p, --page ", "页码", "1") .option("-a, --all", "全页自动翻页") .option("-m, --max-pages ", "最大页数", "5") + .option("--no-resolve", "不解析真实文章链接(保留搜狗中间页地址)") .action(async (query, opts) => { try { - const result = opts.all - ? { query, page: 1, results: await searchSogouAll(query, parseInt(opts.maxPages)) } - : await searchSogou(query, parseInt(opts.page)) + const results = opts.all + ? await searchSogouAll(query, parseInt(opts.maxPages)) + : (await searchSogou(query, parseInt(opts.page))).results + const finalResults = opts.resolve ? await resolveResultsRealUrls(results) : results + const result = { + query, + page: parseInt(opts.page), + results: finalResults, + } process.stdout.write(JSON.stringify(result) + "\n") } catch (e) { const msg = e instanceof Error ? e.message : String(e) diff --git a/src/lib/__test__/fetcher.test.ts b/src/lib/__test__/fetcher.test.ts index 5c652e6..95413a8 100644 --- a/src/lib/__test__/fetcher.test.ts +++ b/src/lib/__test__/fetcher.test.ts @@ -24,17 +24,21 @@ function mockRes(url: string, html: string): Response { describe("searchSogou", () => { beforeEach(() => vi.restoreAllMocks()) - it("解析搜索结果", async () => { - const html = readFileSync(join(fixtureDir, "sogou-search.html"), "utf-8") + it("解析真实搜索结果(公众号名 + timeConvert 时间戳)", async () => { + const html = readFileSync(join(fixtureDir, "sogou-search-real.html"), "utf-8") vi.stubGlobal( "fetch", vi.fn().mockResolvedValue(mockRes("https://weixin.sogou.com/weixin?query=AI", html)), ) const r = await searchSogou("AI") - expect(r.query).toBe("AI") - expect(r.results).toHaveLength(2) - expect(r.results[0].title).toBe("AI文章标题1") - expect(r.results[1].publishTime).toBe("2024-01-14") + expect(r.results.length).toBeGreaterThan(0) + const first = r.results[0] + expect(first.title.length).toBeGreaterThan(0) + // 公众号名来自 .all-time-y2,不再为空 + expect(first.account).toBe("CFD之道") + // publishTime 由 timeConvert 时间戳转换而来,不再是一段 script 源码 + expect(first.publishTime).toMatch(/^\d{4}-\d{2}-\d{2}$/) + expect(first.publishTime).not.toContain("timeConvert") }) it("反爬检测", async () => { @@ -58,15 +62,15 @@ describe("searchSogou", () => { describe("resolveRealUrl", () => { beforeEach(() => vi.restoreAllMocks()) - it("提取真实URL", async () => { - const html = readFileSync(join(fixtureDir, "sogou-redirect.html"), "utf-8") + it("真实 /link 页面:首段已含 https://mp. 前缀,不再重复拼接", async () => { + const html = readFileSync(join(fixtureDir, "sogou-redirect-real.html"), "utf-8") vi.stubGlobal( "fetch", - vi.fn().mockResolvedValue(mockRes("https://weixin.sogou.com/redirect", html)), - ) - expect(await resolveRealUrl("https://weixin.sogou.com/redirect")).toBe( - "https://mp.weixin.qq.com/r/abc_def_123", + vi.fn().mockResolvedValue(mockRes("https://weixin.sogou.com/link?url=test", html)), ) + const url = await resolveRealUrl("https://weixin.sogou.com/link?url=test") + expect(url).toMatch(/^https:\/\/mp\.weixin\.qq\.com\/s\?src=11/) + expect(url).not.toContain("https://mp.https://") }) it("反爬返回空", async () => { diff --git a/src/lib/fetcher.ts b/src/lib/fetcher.ts index 110b72a..e41bef4 100644 --- a/src/lib/fetcher.ts +++ b/src/lib/fetcher.ts @@ -6,13 +6,26 @@ const UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0" const TIMEOUT = 15_000 +// 搜狗 /link 中间页依赖搜索阶段建立的会话 cookie,原生 fetch 不持久化,这里手动维护一个最小 jar +let cookieJar = "" + +function collectCookies(res: Response): void { + const getSetCookie = (res.headers as { getSetCookie?: () => string[] }).getSetCookie + if (typeof getSetCookie !== "function") return + const parts = getSetCookie + .call(res.headers) + .map((c) => c.split(";")[0]) + .filter(Boolean) + if (parts.length) cookieJar = parts.join("; ") +} + function isAnti(url: string, body: string): boolean { const u = url.toLowerCase() const b = body.toLowerCase() return u.includes("antispider") || b.includes("seccoderight") || b.includes("anti.min.css") } -async function fetchWithTimeout(url: string, init?: RequestInit): Promise { +export async function fetchWithTimeout(url: string, init?: RequestInit): Promise { const ctrl = new AbortController() const t = setTimeout(() => ctrl.abort(), TIMEOUT) try { @@ -22,7 +35,7 @@ async function fetchWithTimeout(url: string, init?: RequestInit): Promise = {}): Record { +export function headers(extra: Record = {}): Record { return { Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", @@ -67,6 +80,7 @@ export async function searchSogou( const html = await res.text() if (isAnti(res.url, html)) throw new Error("ANTISPIDER") + collectCookies(res) const $ = cheerio.load(html) const results: SearchResult[] = [] @@ -74,12 +88,15 @@ export async function searchSogou( const $el = $(el) let link = $el.attr("href") ?? "" if (link && !link.startsWith("http")) link = `https://weixin.sogou.com${link}` - const pub = $(`li[id^="sogou_vr_11002601_box_"] .txt-box .s-p .s2`).eq(i).text().trim() + const box = $el.closest('li[id^="sogou_vr_11002601_box_"]') + const s2 = box.find(".txt-box .s-p .s2").text().trim() + const account = box.find(".txt-box .s-p .all-time-y2").text().trim() results.push({ title: $el.text().trim(), link, realUrl: "", - publishTime: pub, + publishTime: parseTimeConvert(s2), + account, page: String(page), }) }) @@ -87,21 +104,51 @@ export async function searchSogou( return { query, page, results } } +function parseTimeConvert(text: string): string { + const m = text.match(/timeConvert\('(\d+)'\)/) + if (!m) return text + return formatTimestamp(Number(m[1])) +} + +function formatTimestamp(ts: number): string { + const d = new Date((ts + 8 * 3600) * 1000) + return d.toISOString().slice(0, 10) +} + export async function resolveRealUrl(sogouUrl: string): Promise { try { - const res = await fetchWithTimeout(sogouUrl, { headers: headers() }) + const hdrs = headers() + if (cookieJar) hdrs["Cookie"] = cookieJar + hdrs["Referer"] = "https://weixin.sogou.com/" + const res = await fetchWithTimeout(sogouUrl, { headers: hdrs }) const html = await res.text() if (isAnti(res.url, html)) return "" const parts: string[] = [] const re = /url\s*\+=\s*['"]([^'"]+)['"]/g let m: RegExpExecArray | null while ((m = re.exec(html)) !== null) parts.push(m[1]) - return parts.length ? "https://mp." + parts.join("").replace(/@/g, "") : "" + if (!parts.length) return "" + const joined = parts.join("").replace(/@/g, "") + if (joined.startsWith("https://mp.") || joined.startsWith("http://mp.")) return joined + return `https://mp.${joined}` } catch { return "" } } +export async function resolveResultsRealUrls(results: SearchResult[]): Promise { + const out: SearchResult[] = [] + for (const r of results) { + let realUrl = "" + if (r.link.includes("weixin.sogou.com/link")) { + realUrl = await resolveRealUrl(r.link) + await sleep(200) + } + out.push({ ...r, realUrl }) + } + return out +} + export async function fetchArticleContent(realUrl: string, referer?: string): Promise { if (!realUrl || realUrl === "https://mp.") return "获取文章内容失败: 未拿到有效的微信公众号文章链接" @@ -121,6 +168,8 @@ function sleep(ms: number) { return new Promise((r) => setTimeout(r, ms)) } +export { sleep } + export async function searchSogouAll(query: string, maxPages = 5): Promise { const all: SearchResult[] = [] for (let p = 1; p <= maxPages; p++) { diff --git a/src/lib/types.ts b/src/lib/types.ts index fee8261..eafb2ab 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -3,6 +3,7 @@ export interface SearchResult { link: string realUrl: string publishTime: string + account: string page: string } @@ -22,3 +23,18 @@ export interface ErrorResponse { error: "antispider" | "network" | "usage" message: string } + +export interface AlbumArticle { + title: string + createTime: number + msgid: string + itemidx: string + url: string +} + +export interface AlbumResponse { + total: string + continueFlag: number + reverseContinueFlag: number + articles: AlbumArticle[] +} diff --git a/src/tests/fixtures/sogou-redirect-real.html b/src/tests/fixtures/sogou-redirect-real.html new file mode 100644 index 0000000..8919d32 --- /dev/null +++ b/src/tests/fixtures/sogou-redirect-real.html @@ -0,0 +1,24 @@ + + + diff --git a/src/tests/fixtures/sogou-search-real.html b/src/tests/fixtures/sogou-search-real.html new file mode 100644 index 0000000..3a5e6af --- /dev/null +++ b/src/tests/fixtures/sogou-search-real.html @@ -0,0 +1,430 @@ + + + + + + + + + + + + + + LLM 知识库的相关微信公众号文章 – 搜狗微信搜索 + + + + + + + + + + + + + + + +
+ + + +
+ + + + +
+
+
+
+ + + + + + + +
+
+ + + +
+
+
+
+ + +
+
+ + + + + + +
+
+
+
+ 以下内容来自微信公众平台 +
+ +
+
+
+ + + + +
+ +
    + + +
  • +
    + +
    +
    +

    +基于AnythingLLM及Ollama搭建本地知识库 +

    +

    知识库管理可以点击左下角的设置按钮打开设置面板如下图所示可以设置语料分割参数也可以点击左上角的按钮,如下图所示其中第一...

    +
    +CFD之道 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +Karpathy的LLM Wiki知识库,为什么需要轻量级知识图谱 +

    +

    公开了他那套"个人 LLM 知识库"的做法.和大部分所谓知识库不一样的是,他不是把一堆 markdown 文件丢进向量库等着检索,而...

    +
    +知识图谱科技 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +LangChain+LLM本地知识库问答:从企业单文档问答到批量文档问答 +

    +

    要么更可以基于langchain里集成的向量数据库和LLM搭建本地知识库问答(此处的向量数据库的独特性在哪呢?举个例子,传统数据库...

    +
    +机器学习AI算法工程 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +LLM实战 | 基于本地知识库打造属于自己的New Bing! +

    +

    知识库+LLM去构建一个基于知识库的问答系统的基本架构,而其中很多模块都可以进行丰富和优化,比如文本分块模块,文本向量化...

    +
    +数据STUDIO +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +基于 LLM 大模型构建企业知识库案例实战 +

    +

    [爱心]今天20点直播主题:基于 LLM 大模型构建企业知识库案例实战[庆祝]直播精彩看点:1、LLM 大模型在工作中的实际应用以及局...

    +
    +架构之美 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +LLM本地知识库问答系统(二):如何正确使用LlamaIndex索引 +

    +

    推荐阅读列表:LLM本地知识库问答系统(一):使用LangChain和LlamaIndex从零构建PDF聊天机器人指南 上一篇文章我们介绍...

    +
    +ArronAI +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +从LangChain+LLM的本地知识库问答到LLM与知识图谱、数据库的结合 +

    +

    如何通过LangChain+LLM实现本地知识库问答GitHub上有一个利用 langchain 思想实现的基于本地知识库的问答应用:langchain-...

    +
    +七月在线实验室 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +1Panel官方出品丨MaxKB:基于LLM大模型的知识库问答系统 +

    +

    与同类基于LLM的知识库问答提供系统相比,MaxKB的核心优势包括:■ 开箱即用:支持直接上传文档、自动爬取在线文档,支持文本...

    +
    +1Panel开源面板 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +春节在家无聊搭建一个懒人客服,基于LLM客服&知识库 +

    +

    #基于LLM的知识库客服 #电商运营实用技巧 #智能客服体验分享 #客服系统搭建心得 #春节在家创意项目 #电商运营 #电商客服 #智能客...

    +
    +大模型知识干货 +
    +
    +
  • + + + + +
  • +
    + +
    +
    +

    +Andrej Karpathy 如何打造LLM 知识库 +

    +

    日来源:Twitter/X最近我发现一个非常有用的方法:使用 LLM 为各种研究兴趣主题构建个人知识库.通过这种方式,我最近的大部分 ...

    +
    +绿电宇宙 +
    +
    +
  • + + + +
+ +
+ 12345678910 + 下一页 + +
找到约853条结果
+
+ +
+ + +
+ + + +
+ + +
+ + +
+
+
+
+ + + + + + + +
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + From 8322dbb5c57ecfebaf351f2fbea3f43367561417 Mon Sep 17 00:00:00 2001 From: Zou Zhao Date: Sun, 20 Sep 2026 06:18:12 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat(album):=20=E6=96=B0=E5=A2=9E=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E5=90=88=E9=9B=86=E6=96=87=E7=AB=A0=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8E=A5=E5=8F=A3=EF=BC=88CLI=20+=20MCP=20+=20skill?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +++++-- docs/README.zh-CN.md | 27 +++++-- skills/mpget.md | 10 ++- src/commands/__test__/mcp.test.ts | 49 ++++++++++++- src/commands/album.ts | 38 ++++++++++ src/commands/mcp.ts | 63 ++++++++++++++-- src/index.ts | 2 + src/lib/__test__/album.test.ts | 114 +++++++++++++++++++++++++++++ src/lib/album.ts | 86 ++++++++++++++++++++++ src/tests/fixtures/album-real.json | 1 + 10 files changed, 390 insertions(+), 27 deletions(-) create mode 100644 src/commands/album.ts create mode 100644 src/lib/__test__/album.test.ts create mode 100644 src/lib/album.ts create mode 100644 src/tests/fixtures/album-real.json diff --git a/README.md b/README.md index 8a14577..5b54acf 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Designed for **agent integration** — structured JSON output, MCP server suppor - **Agent Skill** — `mpget init` injects a skill file into `.claude/skills/` with version sync - **Multi-page search** — automatic pagination with configurable max pages and rate limiting - **Article content extraction** — fetches and cleans WeChat article body text +- **Album article listing** — list all articles in an official account's album (with real mp.weixin.qq.com links) - **Structured JSON output** — all results to stdout, errors to stderr with typed exit codes ## Install @@ -38,15 +39,22 @@ mpget search "key" -a -m 5 # Fetch article content mpget content "https://mp.weixin.qq.com/s/xxx" + +# List articles in an account's album (needs __biz and album_id from an article page) +mpget album "MzkxMTY4NTAyNQ==" "4371775694981152789" -c 10 + +# Fetch the whole album +mpget album "MzkxMTY4NTAyNQ==" "4371775694981152789" --all ``` **Search options:** -| Option | Description | Default | -| ---------------- | ---------------------- | ------- | -| `-p, --page ` | Page number | `1` | -| `-a, --all` | Fetch all pages | `false` | -| `-m, --max ` | Max pages when `--all` | `10` | +| Option | Description | Default | +| ---------------- | ------------------------------------------ | ------- | +| `-p, --page ` | Page number | `1` | +| `-a, --all` | Fetch all pages | `false` | +| `-m, --max ` | Max pages when `--all` | `10` | +| `--no-resolve` | Skip resolving real mp.weixin.qq.com links | `false` | ### MCP Server @@ -54,9 +62,10 @@ mpget content "https://mp.weixin.qq.com/s/xxx" mpget mcp ``` -Starts a stdio-based MCP server exposing two tools: +Starts a stdio-based MCP server exposing three tools: -- **`search`** — query, page, all, maxPages +- **`search`** — query, page, all, maxPages, resolve (default: resolve real links) +- **`album`** — biz, albumId, count, beginMsgid, beginItemidx - **`content`** — url, referer Compatible with any MCP-capable agent (Claude, Cursor, etc.). @@ -81,7 +90,9 @@ All commands output JSON to stdout. Errors go to stderr as structured JSON. { "title": "Article Title", "link": "https://weixin.sogou.com/link?url=...", - "publishTime": "2025-01-01" + "realUrl": "https://mp.weixin.qq.com/s?src=11&...", + "publishTime": "2025-01-01", + "account": "Account Name" } ], "total": 10, diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md index bdfb36b..62e115a 100644 --- a/docs/README.zh-CN.md +++ b/docs/README.zh-CN.md @@ -12,6 +12,7 @@ CLI 工具与 MCP 服务,用于搜索和获取微信公众号文章(基于 - **Agent Skill** — `mpget init` 一键注入 Skill 到 `.claude/skills/`,带版本同步 - **多页搜索** — 自动分页,支持配置最大页数和请求间隔 - **文章内容提取** — 获取并清洗微信公众号文章正文 +- **合集文章列表** — 拉取某公众号合集内全部文章(含真实 mp.weixin.qq.com 链接) - **结构化 JSON 输出** — 结果输出到 stdout,错误输出到 stderr,带类型化退出码 ## 安装 @@ -38,15 +39,22 @@ mpget search "关键词" -a -m 5 # 获取文章内容 mpget content "https://mp.weixin.qq.com/s/xxx" + +# 获取某公众号合集内的文章列表(biz 与 album_id 取自文章页) +mpget album "MzkxMTY4NTAyNQ==" "4371775694981152789" -c 10 + +# 拉取整个合集 +mpget album "MzkxMTY4NTAyNQ==" "4371775694981152789" --all ``` **搜索参数:** -| 参数 | 说明 | 默认值 | -| ---------------- | ------------------ | ------- | -| `-p, --page ` | 页码 | `1` | -| `-a, --all` | 获取全部页 | `false` | -| `-m, --max ` | `--all` 时最大页数 | `10` | +| 参数 | 说明 | 默认值 | +| ---------------- | -------------------------------- | ------- | +| `-p, --page ` | 页码 | `1` | +| `-a, --all` | 获取全部页 | `false` | +| `-m, --max ` | `--all` 时最大页数 | `10` | +| `--no-resolve` | 不解析真实 mp.weixin.qq.com 链接 | `false` | ### MCP Server @@ -54,9 +62,10 @@ mpget content "https://mp.weixin.qq.com/s/xxx" mpget mcp ``` -启动基于 stdio 的 MCP Server,提供两个工具: +启动基于 stdio 的 MCP Server,提供三个工具: -- **`search`** — query, page, all, maxPages +- **`search`** — query, page, all, maxPages, resolve(默认解析真实链接) +- **`album`** — biz, albumId, count, beginMsgid, beginItemidx - **`content`** — url, referer 兼容所有支持 MCP 协议的 Agent(Claude、Cursor 等)。 @@ -81,7 +90,9 @@ mpget init { "title": "文章标题", "link": "https://weixin.sogou.com/link?url=...", - "publishTime": "2025-01-01" + "realUrl": "https://mp.weixin.qq.com/s?src=11&...", + "publishTime": "2025-01-01", + "account": "公众号名" } ], "total": 10, diff --git a/skills/mpget.md b/skills/mpget.md index 2d809c6..e014065 100644 --- a/skills/mpget.md +++ b/skills/mpget.md @@ -11,7 +11,8 @@ cli_version: 1.0.0 ## 命令 -- `mpget search [-p ] [-a] [-m ]` +- `mpget search [-p ] [-a] [-m ] [--no-resolve]` +- `mpget album [-c ] [--all]` - `mpget content [-r ]` - `mpget init` - `mpget --version` @@ -20,6 +21,7 @@ cli_version: 1.0.0 1. 用户问"搜公众号 XXX" → `mpget search ` 2. 需要多页 → `mpget search -a -m 5` -3. 需要正文 → 先 search 拿 realUrl,再 `mpget content ` -4. 反爬(exit 1, error antispider)→ 告知用户搜狗反爬 -5. 版本不对 → 先 `mpget init` 再继续 +3. 需要某公众号的全部/近期文章 → 从任意一篇文章页拿 `var biz` 与 `album_id`,`mpget album --all` +4. 需要正文 → 先 search 拿 realUrl,再 `mpget content ` +5. 反爬(exit 1, error antispider)→ 告知用户搜狗反爬 +6. 版本不对 → 先 `mpget init` 再继续 diff --git a/src/commands/__test__/mcp.test.ts b/src/commands/__test__/mcp.test.ts index 65ceeed..315da58 100644 --- a/src/commands/__test__/mcp.test.ts +++ b/src/commands/__test__/mcp.test.ts @@ -4,14 +4,27 @@ vi.mock("../../lib/fetcher.js", () => ({ searchSogou: vi.fn(), searchSogouAll: vi.fn(), fetchArticleContent: vi.fn(), + resolveResultsRealUrls: vi.fn(), +})) + +vi.mock("../../lib/album.js", () => ({ + fetchAlbumArticles: vi.fn(), })) import { createMcpServer, __test__ } from "../mcp.js" -import { searchSogou, searchSogouAll, fetchArticleContent } from "../../lib/fetcher.js" +import { + searchSogou, + searchSogouAll, + fetchArticleContent, + resolveResultsRealUrls, +} from "../../lib/fetcher.js" +import { fetchAlbumArticles } from "../../lib/album.js" const mockSearch = vi.mocked(searchSogou) const mockSearchAll = vi.mocked(searchSogouAll) const mockContent = vi.mocked(fetchArticleContent) +const mockResolve = vi.mocked(resolveResultsRealUrls) +const mockAlbum = vi.mocked(fetchAlbumArticles) describe("MCP tool handlers", () => { beforeEach(() => { @@ -26,14 +39,17 @@ describe("MCP tool handlers", () => { results: [{ title: "T", link: "L", realUrl: "", publishTime: "P", page: "1" }], } mockSearch.mockResolvedValue(fakeResult) + mockResolve.mockImplementation(async (results) => results) const result = await __test__.handleSearch({ query: "test" }) expect(mockSearch).toHaveBeenCalledWith("test", 1, true) + expect(mockResolve).toHaveBeenCalledWith(fakeResult.results) expect(result.isError).toBe(false) expect(JSON.parse(result.content[0].text)).toEqual(fakeResult) }) it("all=true 时调用 searchSogouAll", async () => { mockSearchAll.mockResolvedValue([]) + mockResolve.mockImplementation(async (results) => results) const result = await __test__.handleSearch({ query: "q", all: true, maxPages: 3 }) expect(mockSearchAll).toHaveBeenCalledWith("q", 3) expect(result.isError).toBe(false) @@ -55,6 +71,37 @@ describe("MCP tool handlers", () => { }) }) + describe("album handler", () => { + it("调用 fetchAlbumArticles 并返回结果", async () => { + const fakeAlbum = { + total: "119", + continueFlag: 1, + reverseContinueFlag: 0, + articles: [ + { + title: "A", + createTime: 1, + msgid: "1", + itemidx: "1", + url: "https://mp.weixin.qq.com/s?a", + }, + ], + } + mockAlbum.mockResolvedValue(fakeAlbum) + const result = await __test__.handleAlbum({ biz: "B", albumId: "A" }) + expect(mockAlbum).toHaveBeenCalledWith({ biz: "B", albumId: "A", count: 10 }) + expect(result.isError).toBe(false) + expect(JSON.parse(result.content[0].text)).toEqual(fakeAlbum) + }) + + it("fetchAlbumArticles 抛错时返回 isError", async () => { + mockAlbum.mockRejectedValue(new Error("ALBUM_RET_-3")) + const result = await __test__.handleAlbum({ biz: "B", albumId: "A" }) + expect(result.isError).toBe(true) + expect(result.content[0].text).toContain("获取合集失败") + }) + }) + describe("content handler", () => { it("调用 fetchArticleContent 并返回结果", async () => { mockContent.mockResolvedValue("文章正文") diff --git a/src/commands/album.ts b/src/commands/album.ts new file mode 100644 index 0000000..b2ef073 --- /dev/null +++ b/src/commands/album.ts @@ -0,0 +1,38 @@ +import { Command } from "commander" +import { fetchAlbumArticles, fetchAlbumArticlesAll } from "../lib/album.js" + +export function setupAlbumCommand(program: Command): void { + program + .command("album ") + .description("获取公众号合集内的文章列表(含真实文章链接)") + .option("-c, --count ", "每页条数(服务端上限 20)", "10") + .option("--begin-msgid ", "翻页起点 msgid(上一页末条)") + .option("--begin-itemidx ", "翻页起点 itemidx(上一页末条)") + .option("-a, --all", "自动翻页拉取整个合集") + .option("-m, --max-pages ", "自动翻页的最大页数", "50") + .action(async (biz, albumId, opts) => { + try { + const result = opts.all + ? await fetchAlbumArticlesAll(biz, albumId, parseInt(opts.maxPages)) + : await fetchAlbumArticles({ + biz, + albumId, + count: parseInt(opts.count), + beginMsgid: opts.beginMsgid, + beginItemidx: opts.beginItemidx, + }) + process.stdout.write(JSON.stringify(result) + "\n") + } catch (e) { + const msg = e instanceof Error ? e.message : String(e) + if (msg.startsWith("HTTP_") || msg.startsWith("NETWORK")) { + process.stderr.write("网络请求失败\n") + } else if (msg.startsWith("ALBUM_RET_")) { + process.stderr.write("合集接口返回错误(可能需要登录)\n") + } else { + process.stderr.write(`错误: ${msg}\n`) + } + process.stdout.write(JSON.stringify({ error: "album", message: msg }) + "\n") + process.exit(1) + } + }) +} diff --git a/src/commands/mcp.ts b/src/commands/mcp.ts index ca52c5a..e2474ac 100644 --- a/src/commands/mcp.ts +++ b/src/commands/mcp.ts @@ -2,7 +2,13 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js" import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js" import { Command } from "commander" -import { searchSogou, searchSogouAll, fetchArticleContent } from "../lib/fetcher.js" +import { + searchSogou, + searchSogouAll, + fetchArticleContent, + resolveResultsRealUrls, +} from "../lib/fetcher.js" +import { fetchAlbumArticles } from "../lib/album.js" import { VERSION, CLI_NAME } from "../version.js" async function handleSearch( @@ -12,12 +18,17 @@ async function handleSearch( const page = (args.page as number) ?? 1 const all = (args.all as boolean) ?? false const maxPages = (args.maxPages as number) ?? 5 + const resolve = (args.resolve as boolean) ?? true try { - const result = all - ? { query, page: 1, results: await searchSogouAll(query, maxPages) } - : await searchSogou(query, page, true) - return { isError: false, content: [{ type: "text", text: JSON.stringify(result) }] } + const results = all + ? await searchSogouAll(query, maxPages) + : (await searchSogou(query, page, true)).results + const finalResults = resolve ? await resolveResultsRealUrls(results) : results + return { + isError: false, + content: [{ type: "text", text: JSON.stringify({ query, page, results: finalResults }) }], + } } catch (e) { const msg = e instanceof Error ? e.message : String(e) if (msg.startsWith("ANTISPIDER")) @@ -41,6 +52,26 @@ async function handleContent( } } +async function handleAlbum( + args: Record, +): Promise<{ isError: boolean; content: Array<{ type: "text"; text: string }> }> { + const biz = args.biz as string + const albumId = args.albumId as string + try { + const result = await fetchAlbumArticles({ + biz, + albumId, + count: (args.count as number | undefined) ?? 10, + beginMsgid: args.beginMsgid as string | undefined, + beginItemidx: args.beginItemidx as string | undefined, + }) + return { isError: false, content: [{ type: "text", text: JSON.stringify(result) }] } + } catch (e) { + const msg = e instanceof Error ? e.message : String(e) + return { isError: true, content: [{ type: "text", text: `获取合集失败: ${msg}` }] } + } +} + export function createMcpServer(): Server { const server = new Server({ name: CLI_NAME, version: VERSION }, { capabilities: { tools: {} } }) @@ -56,10 +87,29 @@ export function createMcpServer(): Server { page: { type: "number", description: "页码,默认 1", default: 1 }, all: { type: "boolean", description: "自动翻页", default: false }, maxPages: { type: "number", description: "最大页数,all=true 时生效", default: 5 }, + resolve: { type: "boolean", description: "解析真实文章链接,默认 true", default: true }, }, required: ["query"], }, }, + { + name: "album", + description: "获取公众号合集内的文章列表(含真实文章链接),需要 biz 与 album_id", + inputSchema: { + type: "object" as const, + properties: { + biz: { + type: "string", + description: "公众号 __biz 值(文章页 var biz,形如 MzkxMTY4NTAyNQ==)", + }, + albumId: { type: "string", description: "合集 ID(文章页 album_id 字段)" }, + count: { type: "number", description: "每页条数,上限 20", default: 10 }, + beginMsgid: { type: "string", description: "翻页起点 msgid" }, + beginItemidx: { type: "string", description: "翻页起点 itemidx" }, + }, + required: ["biz", "albumId"], + }, + }, { name: "content", description: "获取微信公众号文章正文", @@ -78,6 +128,7 @@ export function createMcpServer(): Server { server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params if (name === "search") return handleSearch(args ?? {}) + if (name === "album") return handleAlbum(args ?? {}) if (name === "content") return handleContent(args ?? {}) throw new Error(`Unknown tool: ${name}`) }) @@ -91,7 +142,7 @@ export async function startMcpServer(): Promise { await server.connect(transport) } -export const __test__ = { handleSearch, handleContent } +export const __test__ = { handleSearch, handleContent, handleAlbum } export function setupMcpCommand(program: Command): void { program diff --git a/src/index.ts b/src/index.ts index c7bb3f0..57b0b73 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { setupSearchCommand } from "./commands/search.js" import { setupContentCommand } from "./commands/content.js" import { setupInitCommand } from "./commands/init.js" import { setupMcpCommand } from "./commands/mcp.js" +import { setupAlbumCommand } from "./commands/album.js" const program = new Command() program.name(CLI_NAME).version(VERSION).description("微信公众号内容搜索与获取终端工具") @@ -12,4 +13,5 @@ setupSearchCommand(program) setupContentCommand(program) setupInitCommand(program) setupMcpCommand(program) +setupAlbumCommand(program) program.parse(process.argv) diff --git a/src/lib/__test__/album.test.ts b/src/lib/__test__/album.test.ts new file mode 100644 index 0000000..feab23c --- /dev/null +++ b/src/lib/__test__/album.test.ts @@ -0,0 +1,114 @@ +import { describe, it, expect, vi, beforeEach } from "vitest" +import { readFileSync } from "node:fs" +import { join, dirname } from "node:path" +import { fileURLToPath } from "node:url" +import { fetchAlbumArticles, fetchAlbumArticlesAll } from "../album.js" + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const fixtureDir = join(__dirname, "../../tests/fixtures") + +function mockRes(url: string, json: unknown): Response { + return { + ok: true, + status: 200, + text: () => Promise.resolve(JSON.stringify(json)), + json: () => Promise.resolve(json), + url, + headers: new Headers(), + redirected: false, + statusText: "OK", + type: "basic" as const, + clone: () => mockRes(url, json), + } as Response +} + +const albumJson = JSON.parse(readFileSync(join(fixtureDir, "album-real.json"), "utf-8")) + +describe("fetchAlbumArticles", () => { + beforeEach(() => vi.restoreAllMocks()) + + it("解析真实合集响应:文章列表 + 总数 + 翻页标记", async () => { + vi.stubGlobal( + "fetch", + vi.fn().mockResolvedValue(mockRes("https://mp.weixin.qq.com/mp/appmsgalbum", albumJson)), + ) + const r = await fetchAlbumArticles({ biz: "MzkxMTY4NTAyNQ==", albumId: "4371775694981152789" }) + expect(r.total).toBe("119") + expect(r.continueFlag).toBe(1) + expect(r.articles.length).toBeGreaterThan(0) + const first = r.articles[0] + expect(first.title.length).toBeGreaterThan(0) + expect(first.createTime).toBeGreaterThan(0) + // url 统一转 https + expect(first.url).toMatch(/^https:\/\/mp\.weixin\.qq\.com\/s\?/) + }) + + it("非 0 ret 抛 ALBUM_RET_ 错误", async () => { + vi.stubGlobal( + "fetch", + vi + .fn() + .mockResolvedValue( + mockRes("https://mp.weixin.qq.com/mp/appmsgalbum", { base_resp: { ret: -3 } }), + ), + ) + await expect(fetchAlbumArticles({ biz: "x", albumId: "y" })).rejects.toThrow("ALBUM_RET_-3") + }) +}) + +describe("fetchAlbumArticlesAll", () => { + beforeEach(() => vi.restoreAllMocks()) + + it("翻页聚合直到 continue_flag 为 0", async () => { + const page1 = { + base_resp: { ret: 0 }, + getalbum_resp: { + article_list: [ + { + title: "A", + create_time: "1", + msgid: "100", + itemidx: "1", + url: "http://mp.weixin.qq.com/s?a", + }, + { + title: "B", + create_time: "2", + msgid: "99", + itemidx: "1", + url: "http://mp.weixin.qq.com/s?b", + }, + ], + base_info: { article_count: "3" }, + continue_flag: 1, + }, + } + const page2 = { + base_resp: { ret: 0 }, + getalbum_resp: { + article_list: [ + { + title: "C", + create_time: "3", + msgid: "98", + itemidx: "1", + url: "http://mp.weixin.qq.com/s?c", + }, + ], + base_info: { article_count: "3" }, + continue_flag: 0, + }, + } + const fetchMock = vi + .fn() + .mockResolvedValueOnce(mockRes("u", page1)) + .mockResolvedValueOnce(mockRes("u", page2)) + vi.stubGlobal("fetch", fetchMock) + const r = await fetchAlbumArticlesAll("biz", "album") + expect(r.articles.map((a) => a.title)).toEqual(["A", "B", "C"]) + // 第二次请求携带上一页末条的翻页游标 + const secondUrl = fetchMock.mock.calls[1][0] as string + expect(secondUrl).toContain("begin_msgid=99") + expect(secondUrl).toContain("begin_itemidx=1") + }) +}) diff --git a/src/lib/album.ts b/src/lib/album.ts new file mode 100644 index 0000000..2fc6ee1 --- /dev/null +++ b/src/lib/album.ts @@ -0,0 +1,86 @@ +import { fetchWithTimeout, headers } from "./fetcher.js" +import type { AlbumArticle, AlbumResponse } from "./types.js" + +const ALBUM_URL = "https://mp.weixin.qq.com/mp/appmsgalbum" + +export interface AlbumParams { + biz: string + albumId: string + count?: number + beginMsgid?: string + beginItemidx?: string +} + +function isSuccessData(data: Record): boolean { + const base = data.base_resp as { ret?: number } | undefined + return base?.ret === 0 +} + +function normalizeUrl(url: string): string { + return url.replace(/^http:\/\//, "https://") +} + +export async function fetchAlbumArticles(params: AlbumParams): Promise { + const search = new URLSearchParams({ + action: "getalbum", + scene: "1", + f: "json", + __biz: params.biz, + album_id: params.albumId, + count: String(params.count ?? 10), + }) + if (params.beginMsgid) search.set("begin_msgid", params.beginMsgid) + if (params.beginItemidx) search.set("begin_itemidx", params.beginItemidx) + + const res = await fetchWithTimeout(`${ALBUM_URL}?${search}`, { + headers: headers({ Referer: "https://mp.weixin.qq.com/" }), + }) + if (res.status !== 200) throw new Error(`HTTP_${res.status}`) + + const data = (await res.json()) as Record + if (!isSuccessData(data)) + throw new Error(`ALBUM_RET_${(data.base_resp as { ret?: number })?.ret}`) + + const resp = data.getalbum_resp as Record | undefined + const list = (resp?.article_list as Array> | undefined) ?? [] + const baseInfo = (resp?.base_info as Record | undefined) ?? {} + + const articles: AlbumArticle[] = list.map((a) => ({ + title: String(a.title ?? ""), + createTime: Number(a.create_time ?? 0), + msgid: String(a.msgid ?? ""), + itemidx: String(a.itemidx ?? ""), + url: normalizeUrl(String(a.url ?? "")), + })) + + return { + total: String(baseInfo.article_count ?? ""), + continueFlag: Number(resp?.continue_flag ?? 0), + reverseContinueFlag: Number(resp?.reverse_continue_flag ?? 0), + articles, + } +} + +export async function fetchAlbumArticlesAll( + biz: string, + albumId: string, + maxPages = 50, +): Promise { + let beginMsgid: string | undefined + let beginItemidx: string | undefined + let total = "" + const all: AlbumArticle[] = [] + + for (let page = 1; page <= maxPages; page++) { + const r = await fetchAlbumArticles({ biz, albumId, beginMsgid, beginItemidx }) + if (r.total) total = r.total + if (!r.articles.length) break + all.push(...r.articles) + if (!r.continueFlag) break + const last = r.articles[r.articles.length - 1] + beginMsgid = last.msgid + beginItemidx = last.itemidx + } + + return { total, continueFlag: 0, reverseContinueFlag: 0, articles: all } +} diff --git a/src/tests/fixtures/album-real.json b/src/tests/fixtures/album-real.json new file mode 100644 index 0000000..e15e730 --- /dev/null +++ b/src/tests/fixtures/album-real.json @@ -0,0 +1 @@ +{"base_resp":{"exportkey_token":"","ret":0},"getalbum_resp":{"article_list":[{"cover_img_1_1":"https://mmbiz.qpic.cn/sz_mmbiz_jpg/5lJ4HUd9eVPg5uJ5qwdXQakny0QjxWwicxYY7dzEPibJpsMCTD9A26zM3ibOhp69qR7qTsArjBPr0p6LYNFpicw6dXa3J4n1LvoXBqAHzrN68So/300","cover_theme_color":{"b":"168","g":"162","r":"155"},"create_time":"1789722873","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247520242_1","msgid":"2247520242","title":"AI 圈爆火的 Jev 是什么?如何在 TraeCode 中使用","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247520242&idx=1&sn=dc84b775efc929c0e5e8d7bcc1a99bb8&chksm=c11aab3cf66d222a08ea2d30a2e20ca595a0729bfefbf2c4350689805bd730de2fd6732e1e28#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/mmbiz_jpg/5lJ4HUd9eVOZTJ63roVZib5T2aCItTtuPyhKfEcwOC8JdKcPxkEKFnLqcHAegia5PCQyqrkSMibP8m5UkHwa7NnANyvrvjeRicsSAv6hvfYwU4E/300","cover_theme_color":{"b":"175","g":"169","r":"162"},"create_time":"1789636480","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247520153_1","msgid":"2247520153","title":"如何用 TraeCode 构建个人知识库(Wiki)","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247520153&idx=1&sn=c5d44a247c80e79d96d055c2815570db&chksm=c11aab57f66d2241f4a2cd1d4df893e0c676a367ca6c627fc3dcf382305f06ec82754e9ffab8#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/mmbiz_jpg/5lJ4HUd9eVNjFPjVysBzyU96w143G8D6vcU1Dl0u2BPSCnlD6hiakBWTTlrTxKOynQgn7NE8hkrBl06Y74F3EUj4ocMqquLyHRTmsf4ic319s/300","cover_theme_color":{"b":"168","g":"162","r":"155"},"create_time":"1789551367","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247520079_1","msgid":"2247520079","title":"从 0 到百万级关注:我用 TraeCode 做了一款大学生求职应用","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247520079&idx=1&sn=3197e47a171e8b82ac6addc68a780e0a&chksm=c11aab81f66d2297ef7bd61bb55b74545bd2dca5affeee466a2645b678156a7d475ff2c24b3e#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/sz_mmbiz_jpg/5lJ4HUd9eVN3emBd2QafoRuAC7ymkKqNYnvksk4CFBLjic27kvTQmQlHZe8vvt2oIFibnoMHJJ1tXuTUP51LZH9CwQCdmJj8icK06mA1HEtGks/300","cover_theme_color":{"b":"174","g":"168","r":"161"},"create_time":"1789378126","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247519706_1","msgid":"2247519706","title":"模型怎么选?TRAE 真实用户经验:7 个场景直接对号入座","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247519706&idx=1&sn=8c46f8ea60b26d9f7af71ab96a18e15b&chksm=c11aa914f66d20027db4a6b3c7f53d9166203de9cddec4d213bc8a20e3e77ad487d80b9cfd28#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/sz_mmbiz_jpg/5lJ4HUd9eVPNxG4WMibLGstnbKXNwAtzkzuSF6FYPwI21bWE0Ce9NZ46aJkIB6nc35s6G57hegR1mlbZZT8G48DRqOoRTOmhjC6gOiakGst5M/300","cover_theme_color":{"b":"250","g":"250","r":"250"},"create_time":"1787132456","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247518932_1","msgid":"2247518932","title":"7 大热门 TraeWork 插件推荐(含提示词)","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247518932&idx=1&sn=33ca822030f1307416abef5e602d58f8&chksm=c11aae1af66d270cde94711490eea6fa947a666f5da84b776633ccbf190c35d2b85a693f81a6#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/mmbiz_jpg/5lJ4HUd9eVNT284BYK7XsKM9gmew3TocjR1MpVkndmjkOmyMAFvbNcIsNXEYD1WY6zJj9iad6mIOrl95IIbcicZicjtVr8s8ngsM8uFECq0lhg/300","cover_theme_color":{"b":"249","g":"249","r":"249"},"create_time":"1786158000","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247517278_1","msgid":"2247517278","title":"更新焦虑有救了!当我把选题、文案、配图全交给 AI.....","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247517278&idx=1&sn=d33777e62f518078e57a4f986b808172&chksm=c11aa090f66d298638efd2c73daa1942eeb3fa3d9149f20a85f76f49e5d7a98d62b37b5862dc#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/sz_mmbiz_jpg/5lJ4HUd9eVPdenffopCIwp0YEchUBLLbtoaR8Yvy0Q5wicCNMq0ZxEiaTLYUyEJgSvm9ibWcKa3ibVrHiaV7NT44pfbjTiaXBLXkvtANCuLYpNudE/300","cover_theme_color":{"b":"250","g":"250","r":"250"},"create_time":"1785312000","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247516496_1","msgid":"2247516496","title":"从内容选题到复盘,TRAE Work 让 1 个人顶 1 支团队","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247516496&idx=1&sn=3e84bb96aa1bfc1155a1f0e31ed4f6a9&chksm=c11aa59ef66d2c8878c1dc3f985348fa8fb55a0bcab3e842c17735ccaf0a8775af089009d096#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/mmbiz_jpg/5lJ4HUd9eVPc0Zz75Ur3KlNe1RIRRvuIIlicvg5ibyP9oyzJfKVXawfg4W4fYNicGmicCLaVEX2SH35kQG7dibdmgl8Po9lU6mfLdFXO7oyTsAaw/300","cover_theme_color":{"b":"175","g":"169","r":"162"},"create_time":"1784718622","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247516202_1","msgid":"2247516202","title":"用 TRAE Work,1 个人也能轻松做好自媒体","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247516202&idx=1&sn=49297c4237f1e8859799e4455b77558d&chksm=c11aa4e4f66d2df2c35f1ec72bbef82528068bb86ca5bced83ef7e757718d87272f81a365a93#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/mmbiz_jpg/5lJ4HUd9eVNmcF4HRh7d1xyV6icUrOvwRzk1ytsE0astV9gnq9pXqmunDWRGKJmeyqXfnqPqiafmu8ibuiaC6jibWjgFLN7eQr8PXz3JIQjqMz5s/300","cover_theme_color":{"b":"175","g":"169","r":"162"},"create_time":"1784639624","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247516180_1","msgid":"2247516180","title":"万字长文|数据分析 7 大场景实战教程","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247516180&idx=1&sn=0dd23bbb1e622ffcacf93eb9a82bd53f&chksm=c11aa4daf66d2dcc8fca9826726ab2d72a6bb85097da605be2ff94f02e1cc44c98d4b3dde843#rd","user_read_status":"0"},{"cover_img_1_1":"https://mmbiz.qpic.cn/sz_mmbiz_jpg/5lJ4HUd9eVNqyR8e2NcYVFn6TBSsvrP7Zdm8yc19KmibPzia03ia8KuicuZ2ezU7Gd415wtsK7m5p9n92TDlibQSJXBh6SuFvn8Qd1DtRbz8XJjo/300","cover_theme_color":{"b":"174","g":"168","r":"161"},"create_time":"1784262067","is_pay_subscribe":"0","is_read":"0","item_show_type":"0","itemidx":"1","key":"3911685025_2247515840_1","msgid":"2247515840","title":"只需 5 分钟,TRAE Work 教你免费换“皮肤”","title_gen_type":"0","tts_is_ban":"0","url":"http://mp.weixin.qq.com/s?__biz=MzkxMTY4NTAyNQ==&mid=2247515840&idx=1&sn=8791cb975cb22bc792346c189d2742df&chksm=c11a9a0ef66d1318e5d5daa8413547b6741b90f8681ccc80012c7cf2c9a2df41aa26cf736d3a#rd","user_read_status":"0"}],"base_info":{"article_count":"119","brand_icon":"http://mmbiz.qpic.cn/mmbiz_png/oQ0houcyEiciawiaDfo86x1WBFNt62IH9vUmwT2p36x5XHQz5zjWslK2fL6aib9xSWXSD8SsZYWHW0ibhGXrw0dw5Vg/0?wx_fmt=png","cover":"","cover_ban":"0","description":"","fee":"0","is_first_screen":"1","is_numbered":"0","is_paid":"0","is_reverse":"1","isupdating":"1","needpay":"0","nickname":"TRAE.ai","public_tag_content_num":"3771","public_tag_link":"https://mp.weixin.qq.com/mp/publictag?action=get&tag_id=714417184910082049#wechat_redirect","read_count":"392542","service_type":"0","share_brand_icon":"http://wx.qlogo.cn/mmhead/KetjXWSVppuqV9iahrSDn3PVdrwukgkcLwbEbHm4yFwHdXCibaIQFSRysKOjjfcSh19MLwic0MAhdU/0","subtype":"0","title":"最佳实践","type":"0","update_frequence":{"month":"0"},"username":"gh_f5ae7e78ca23"},"continue_flag":"1","is_pay_subscribe":"0","is_show_subscribe":"0","reverse_continue_flag":"0","verify_status":"2"}} \ No newline at end of file From 6197a63b9fb631c8b0ec25295e2cf1842ae85276 Mon Sep 17 00:00:00 2001 From: Zou Zhao Date: Sun, 20 Sep 2026 06:19:30 +0800 Subject: [PATCH 4/5] =?UTF-8?q?chore:=20prettier=20=E5=BF=BD=E7=95=A5=20pn?= =?UTF-8?q?pm-lock=20=E4=B8=8E=20fixtures=EF=BC=88=E7=94=9F=E6=88=90/?= =?UTF-8?q?=E6=8A=93=E5=8F=96=E6=A0=B7=E6=9C=AC=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d4b0fed --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +pnpm-lock.yaml +src/tests/fixtures/ From 66d16de501122043f44ed2e55507c6442151224c Mon Sep 17 00:00:00 2001 From: Zou Zhao Date: Sun, 20 Sep 2026 08:06:06 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=E6=A0=B9=E6=8D=AE=20ocr=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=AE=A1=E6=A0=B8=E6=84=8F=E8=A7=81=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=81=A5=E5=A3=AE=E6=80=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - album 命令:校验 --count/--max-pages 为正整数,biz/albumId 非空 - fetchAlbumArticles:count clamp 到 [1,20],网络错误带 NETWORK: 前缀与 cause - fetchAlbumArticlesAll:支持 count 与起始游标,maxPages 截断时如实返回 continueFlag - resolveResultsRealUrls:有界并发解析 + 重复链接去重 - cookie jar 按名合并而非整段覆盖,避免并发覆盖 - timeConvert 兼容单双引号;搜狗时间按北京时区常量说明 - MCP:biz/albumId 空值校验,all 模式 page 归一为 1,工具描述字段名对齐 --- .gitignore | 3 ++ src/commands/album.ts | 30 +++++++++++++--- src/commands/mcp.ts | 15 ++++++-- src/commands/search.ts | 2 +- src/lib/__test__/album.test.ts | 65 ++++++++++++++++++++++++++++++++++ src/lib/album.ts | 49 ++++++++++++++++++------- src/lib/fetcher.ts | 55 ++++++++++++++++++++++------ 7 files changed, 189 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 26659ed..a704d96 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ playwright-report/ .history/ .iga/ + +# 临时中间结果 +.tmp/ diff --git a/src/commands/album.ts b/src/commands/album.ts index b2ef073..f6c8b96 100644 --- a/src/commands/album.ts +++ b/src/commands/album.ts @@ -1,6 +1,12 @@ import { Command } from "commander" import { fetchAlbumArticles, fetchAlbumArticlesAll } from "../lib/album.js" +function parsePositiveInt(value: string, name: string): number { + const n = Number(value) + if (!Number.isInteger(n) || n <= 0) throw new Error(`USAGE: ${name} 必须为正整数`) + return n +} + export function setupAlbumCommand(program: Command): void { program .command("album ") @@ -12,26 +18,42 @@ export function setupAlbumCommand(program: Command): void { .option("-m, --max-pages ", "自动翻页的最大页数", "50") .action(async (biz, albumId, opts) => { try { + if (!biz || !albumId) throw new Error("USAGE: biz 与 albumId 不能为空") + const count = parsePositiveInt(opts.count, "--count") + const maxPages = parsePositiveInt(opts.maxPages, "--max-pages") const result = opts.all - ? await fetchAlbumArticlesAll(biz, albumId, parseInt(opts.maxPages)) + ? await fetchAlbumArticlesAll(biz, albumId, { + maxPages, + count, + beginMsgid: opts.beginMsgid, + beginItemidx: opts.beginItemidx, + }) : await fetchAlbumArticles({ biz, albumId, - count: parseInt(opts.count), + count, beginMsgid: opts.beginMsgid, beginItemidx: opts.beginItemidx, }) process.stdout.write(JSON.stringify(result) + "\n") } catch (e) { const msg = e instanceof Error ? e.message : String(e) - if (msg.startsWith("HTTP_") || msg.startsWith("NETWORK")) { + if (msg.startsWith("USAGE")) { + process.stderr.write("参数错误\n") + process.stdout.write(JSON.stringify({ error: "usage", message: msg }) + "\n") + } else if (msg.startsWith("NETWORK")) { + process.stderr.write("网络请求失败\n") + process.stdout.write(JSON.stringify({ error: "network", message: msg }) + "\n") + } else if (msg.startsWith("HTTP_")) { process.stderr.write("网络请求失败\n") + process.stdout.write(JSON.stringify({ error: "network", message: msg }) + "\n") } else if (msg.startsWith("ALBUM_RET_")) { process.stderr.write("合集接口返回错误(可能需要登录)\n") + process.stdout.write(JSON.stringify({ error: "album", message: msg }) + "\n") } else { process.stderr.write(`错误: ${msg}\n`) + process.stdout.write(JSON.stringify({ error: "album", message: msg }) + "\n") } - process.stdout.write(JSON.stringify({ error: "album", message: msg }) + "\n") process.exit(1) } }) diff --git a/src/commands/mcp.ts b/src/commands/mcp.ts index e2474ac..37aa701 100644 --- a/src/commands/mcp.ts +++ b/src/commands/mcp.ts @@ -27,7 +27,12 @@ async function handleSearch( const finalResults = resolve ? await resolveResultsRealUrls(results) : results return { isError: false, - content: [{ type: "text", text: JSON.stringify({ query, page, results: finalResults }) }], + content: [ + { + type: "text", + text: JSON.stringify({ query, page: all ? 1 : page, results: finalResults }), + }, + ], } } catch (e) { const msg = e instanceof Error ? e.message : String(e) @@ -57,6 +62,12 @@ async function handleAlbum( ): Promise<{ isError: boolean; content: Array<{ type: "text"; text: string }> }> { const biz = args.biz as string const albumId = args.albumId as string + if (!biz || !albumId) { + return { + isError: true, + content: [{ type: "text", text: "获取合集失败: biz 与 albumId 不能为空" }], + } + } try { const result = await fetchAlbumArticles({ biz, @@ -94,7 +105,7 @@ export function createMcpServer(): Server { }, { name: "album", - description: "获取公众号合集内的文章列表(含真实文章链接),需要 biz 与 album_id", + description: "获取公众号合集内的文章列表(含真实文章链接),需要 biz 与 albumId", inputSchema: { type: "object" as const, properties: { diff --git a/src/commands/search.ts b/src/commands/search.ts index 286a35b..6be0388 100644 --- a/src/commands/search.ts +++ b/src/commands/search.ts @@ -17,7 +17,7 @@ export function setupSearchCommand(program: Command): void { const finalResults = opts.resolve ? await resolveResultsRealUrls(results) : results const result = { query, - page: parseInt(opts.page), + page: opts.all ? 1 : parseInt(opts.page), results: finalResults, } process.stdout.write(JSON.stringify(result) + "\n") diff --git a/src/lib/__test__/album.test.ts b/src/lib/__test__/album.test.ts index feab23c..f5646a9 100644 --- a/src/lib/__test__/album.test.ts +++ b/src/lib/__test__/album.test.ts @@ -54,6 +54,24 @@ describe("fetchAlbumArticles", () => { ) await expect(fetchAlbumArticles({ biz: "x", albumId: "y" })).rejects.toThrow("ALBUM_RET_-3") }) + + it("count 被 clamp 到 [1,20]", async () => { + const fetchMock = vi + .fn() + .mockResolvedValue(mockRes("https://mp.weixin.qq.com/mp/appmsgalbum", albumJson)) + vi.stubGlobal("fetch", fetchMock) + await fetchAlbumArticles({ biz: "x", albumId: "y", count: 100 }) + expect(fetchMock.mock.calls[0][0]).toContain("count=20") + await fetchAlbumArticles({ biz: "x", albumId: "y", count: -5 }) + expect(fetchMock.mock.calls[1][0]).toContain("count=1") + }) + + it("网络失败时抛 NETWORK: 前缀错误", async () => { + vi.stubGlobal("fetch", vi.fn().mockRejectedValue(new TypeError("fetch failed"))) + await expect(fetchAlbumArticles({ biz: "x", albumId: "y" })).rejects.toThrow( + /^NETWORK: fetch failed/, + ) + }) }) describe("fetchAlbumArticlesAll", () => { @@ -106,9 +124,56 @@ describe("fetchAlbumArticlesAll", () => { vi.stubGlobal("fetch", fetchMock) const r = await fetchAlbumArticlesAll("biz", "album") expect(r.articles.map((a) => a.title)).toEqual(["A", "B", "C"]) + expect(r.continueFlag).toBe(0) // 第二次请求携带上一页末条的翻页游标 const secondUrl = fetchMock.mock.calls[1][0] as string expect(secondUrl).toContain("begin_msgid=99") expect(secondUrl).toContain("begin_itemidx=1") }) + + it("maxPages 截断时 continueFlag 保留为 1(不误报完整)", async () => { + const page1 = { + base_resp: { ret: 0 }, + getalbum_resp: { + article_list: [ + { + title: "A", + create_time: "1", + msgid: "100", + itemidx: "1", + url: "http://mp.weixin.qq.com/s?a", + }, + ], + base_info: { article_count: "50" }, + continue_flag: 1, + }, + } + vi.stubGlobal("fetch", vi.fn().mockResolvedValue(mockRes("u", page1))) + const r = await fetchAlbumArticlesAll("biz", "album", { maxPages: 1, count: 10 }) + expect(r.articles.length).toBe(1) + expect(r.continueFlag).toBe(1) + }) + + it("count 传递到每一页请求", async () => { + const page1 = { + base_resp: { ret: 0 }, + getalbum_resp: { + article_list: [ + { + title: "A", + create_time: "1", + msgid: "100", + itemidx: "1", + url: "http://mp.weixin.qq.com/s?a", + }, + ], + base_info: { article_count: "3" }, + continue_flag: 0, + }, + } + const fetchMock = vi.fn().mockResolvedValue(mockRes("u", page1)) + vi.stubGlobal("fetch", fetchMock) + await fetchAlbumArticlesAll("biz", "album", { maxPages: 3, count: 20 }) + expect(fetchMock.mock.calls[0][0]).toContain("count=20") + }) }) diff --git a/src/lib/album.ts b/src/lib/album.ts index 2fc6ee1..80de080 100644 --- a/src/lib/album.ts +++ b/src/lib/album.ts @@ -21,20 +21,26 @@ function normalizeUrl(url: string): string { } export async function fetchAlbumArticles(params: AlbumParams): Promise { + const count = Math.min(20, Math.max(1, params.count ?? 10)) const search = new URLSearchParams({ action: "getalbum", scene: "1", f: "json", __biz: params.biz, album_id: params.albumId, - count: String(params.count ?? 10), + count: String(count), }) - if (params.beginMsgid) search.set("begin_msgid", params.beginMsgid) - if (params.beginItemidx) search.set("begin_itemidx", params.beginItemidx) + if (params.beginMsgid !== undefined) search.set("begin_msgid", params.beginMsgid) + if (params.beginItemidx !== undefined) search.set("begin_itemidx", params.beginItemidx) - const res = await fetchWithTimeout(`${ALBUM_URL}?${search}`, { - headers: headers({ Referer: "https://mp.weixin.qq.com/" }), - }) + let res: Response + try { + res = await fetchWithTimeout(`${ALBUM_URL}?${search}`, { + headers: headers({ Referer: "https://mp.weixin.qq.com/" }), + }) + } catch (e) { + throw new Error(`NETWORK: ${e instanceof Error ? e.message : String(e)}`, { cause: e }) + } if (res.status !== 200) throw new Error(`HTTP_${res.status}`) const data = (await res.json()) as Record @@ -61,20 +67,39 @@ export async function fetchAlbumArticles(params: AlbumParams): Promise { - let beginMsgid: string | undefined - let beginItemidx: string | undefined + const maxPages = opts.maxPages ?? 50 + let beginMsgid: string | undefined = opts.beginMsgid + let beginItemidx: string | undefined = opts.beginItemidx let total = "" + let lastContinue = 1 const all: AlbumArticle[] = [] for (let page = 1; page <= maxPages; page++) { - const r = await fetchAlbumArticles({ biz, albumId, beginMsgid, beginItemidx }) + const r = await fetchAlbumArticles({ + biz, + albumId, + count: opts.count ?? 10, + beginMsgid, + beginItemidx, + }) if (r.total) total = r.total - if (!r.articles.length) break + lastContinue = r.continueFlag + if (!r.articles.length) { + lastContinue = 0 + break + } all.push(...r.articles) if (!r.continueFlag) break const last = r.articles[r.articles.length - 1] @@ -82,5 +107,5 @@ export async function fetchAlbumArticlesAll( beginItemidx = last.itemidx } - return { total, continueFlag: 0, reverseContinueFlag: 0, articles: all } + return { total, continueFlag: lastContinue, reverseContinueFlag: 0, articles: all } } diff --git a/src/lib/fetcher.ts b/src/lib/fetcher.ts index e41bef4..c0f6c7e 100644 --- a/src/lib/fetcher.ts +++ b/src/lib/fetcher.ts @@ -9,6 +9,17 @@ const TIMEOUT = 15_000 // 搜狗 /link 中间页依赖搜索阶段建立的会话 cookie,原生 fetch 不持久化,这里手动维护一个最小 jar let cookieJar = "" +// 按 cookie 名合并,新值覆盖同名旧值,避免并发搜索时互相覆盖整个 jar +function mergeCookies(jar: string, incoming: string[]): string { + const merged = new Map() + for (const part of [...jar.split("; "), ...incoming]) { + if (!part) continue + const eq = part.indexOf("=") + if (eq > 0) merged.set(part.slice(0, eq), part.slice(eq + 1)) + } + return [...merged.entries()].map(([k, v]) => `${k}=${v}`).join("; ") +} + function collectCookies(res: Response): void { const getSetCookie = (res.headers as { getSetCookie?: () => string[] }).getSetCookie if (typeof getSetCookie !== "function") return @@ -16,7 +27,7 @@ function collectCookies(res: Response): void { .call(res.headers) .map((c) => c.split(";")[0]) .filter(Boolean) - if (parts.length) cookieJar = parts.join("; ") + if (parts.length) cookieJar = mergeCookies(cookieJar, parts) } function isAnti(url: string, body: string): boolean { @@ -105,13 +116,16 @@ export async function searchSogou( } function parseTimeConvert(text: string): string { - const m = text.match(/timeConvert\('(\d+)'\)/) + const m = text.match(/timeConvert\(['"](\d+)['"]\)/) if (!m) return text return formatTimestamp(Number(m[1])) } +// 搜狗时间戳按北京时间(UTC+8)展示日期,与搜狗页面一致 +const CHINA_TZ_OFFSET_SECONDS = 8 * 3600 + function formatTimestamp(ts: number): string { - const d = new Date((ts + 8 * 3600) * 1000) + const d = new Date((ts + CHINA_TZ_OFFSET_SECONDS) * 1000) return d.toISOString().slice(0, 10) } @@ -136,16 +150,35 @@ export async function resolveRealUrl(sogouUrl: string): Promise { } } -export async function resolveResultsRealUrls(results: SearchResult[]): Promise { - const out: SearchResult[] = [] - for (const r of results) { - let realUrl = "" - if (r.link.includes("weixin.sogou.com/link")) { - realUrl = await resolveRealUrl(r.link) - await sleep(200) +// 逐条 resolve 独立请求,用有界并发控制速率,并对重复链接去重(只请求一次) +export async function resolveResultsRealUrls( + results: SearchResult[], + opts: { concurrency?: number } = {}, +): Promise { + const concurrency = opts.concurrency ?? 4 + const out: SearchResult[] = new Array(results.length) + const seen = new Set() + let cursor = 0 + + const worker = async (): Promise => { + for (;;) { + const i = cursor++ + if (i >= results.length) return + const r = results[i] + let realUrl = "" + if (r.link.includes("weixin.sogou.com/link") && !seen.has(r.link)) { + seen.add(r.link) + realUrl = await resolveRealUrl(r.link) + await sleep(100) + } + out[i] = { ...r, realUrl } } - out.push({ ...r, realUrl }) } + + const workers = Array.from({ length: Math.min(concurrency, Math.max(results.length, 1)) }, () => + worker(), + ) + await Promise.all(workers) return out }