diff --git a/README.md b/README.md index f061634b..73240385 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,13 @@ Show that your project uses pkg.pr.new by adding a badge to your README: [![pkg.pr.new](https://pkg.pr.new/badge/stackblitz-labs/pkg.pr.new)](https://pkg.pr.new/~/stackblitz-labs/pkg.pr.new) +

+ Growth Statistics
+ Orgs & Repos + PRs & Branches + Commits +

+ ### How to Get a Badge for Your Repository 1. **Automatically on Repository Page**: diff --git a/packages/app/app/pages/~/growth.vue b/packages/app/app/pages/~/growth.vue new file mode 100644 index 00000000..9f6d4246 --- /dev/null +++ b/packages/app/app/pages/~/growth.vue @@ -0,0 +1,562 @@ + + + + + diff --git a/packages/app/package.json b/packages/app/package.json index 4cb43edb..8e430027 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "nuxi build", "dev": "nuxi dev", + "preview": "nuxi preview", "generate": "nuxi generate", "vendor:octokit": "tsx script/octokit.ts", "prepare": "nuxi prepare", @@ -21,10 +22,16 @@ "@nuxtjs/mdc": "0.17.0", "@octokit/app": "^15.1.1", "@octokit/graphql": "^8.1.1", + "@octokit/openapi-types": "^25.1.0", "@octokit/plugin-paginate-rest": "^11.3.6", + "@octokit/rest": "^22.0.0", "@octokit/webhooks": "^13.4.1", "@vueuse/core": "^12.2.0", "@vueuse/nuxt": "^12.2.0", + "chart.js": "^4.5.0", + "chartjs-adapter-date-fns": "^3.0.0", + "chartjs-plugin-rough": "^0.2.0", + "fflate": "^0.8.2", "marked": "^15.0.4", "nuxt": "^3.15.0", "nuxt-shiki": "0.3.0", @@ -33,6 +40,7 @@ "string-similarity": "^4.0.4", "unstorage": "^1.16.0", "vue": "^3.5.13", + "vue-chartjs": "^5.3.2", "vue-router": "^4.4.3", "zod": "^3.23.8" }, diff --git a/packages/app/server/api/chart.get.ts b/packages/app/server/api/chart.get.ts new file mode 100644 index 00000000..c15e20ea --- /dev/null +++ b/packages/app/server/api/chart.get.ts @@ -0,0 +1,148 @@ +import { defineEventHandler, H3Event } from "h3"; +import { useOctokitInstallation } from "../utils/octokit"; +import { unzipSync, strFromU8 } from "fflate"; + +function extractCountsBlock(content: string): any | null { + const lines = content.split("\n"); + let startIdx = -1; + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes("Counts: {")) { + startIdx = i; + break; + } + } + if (startIdx === -1) return null; + // Collect lines until closing } + const blockLines = []; + for (let i = startIdx; i < lines.length; i++) { + blockLines.push(lines[i]); + if (lines[i].trim().endsWith("}")) break; + } + // Join and clean up + let block = blockLines.join("\n"); + // Remove the leading 'Counts: ' and timestamps + block = block.replace(/.*Counts: /, ""); + block = block.replace(/^[^\{]*\{/, "{"); // Remove anything before first { + // Remove timestamps at the start of each line + block = block.replace(/^[0-9TZ\-:\.]+Z /gm, ""); + // Convert JS object to JSON (add quotes) + block = block.replace(/([a-zA-Z0-9_]+):/g, '"$1":'); + try { + return JSON.parse(block); + } catch (e) { + return null; + } +} + +let cachedData: any = null; +let lastFetch = 0; +const CACHE_DURATION = 7 * 24 * 60 * 60 * 1000; // 1 week in ms + +export default defineEventHandler(async (event: H3Event) => { + try { + if (cachedData && Date.now() - lastFetch < CACHE_DURATION) { + return cachedData; + } + const owner = "stackblitz-labs"; + const repo = "pkg.pr.new"; + const workflowId = "stats.yml"; + + const octokit = await useOctokitInstallation(event, owner, repo); + + const runs = await octokit.paginate(octokit.rest.actions.listWorkflowRuns, { + owner, + repo, + workflow_id: workflowId, + per_page: 100, + status: "success", + }); + + // Only process the latest 100 runs for performance + const latestRuns = runs.slice(0, 100); + + // 4. For each run, download logs, unzip, and extract Counts + const results = []; + for (const run of latestRuns) { + let stats = null; + try { + const logsResponse = await octokit.rest.actions.downloadWorkflowRunLogs( + { + owner, + repo, + run_id: run.id, + }, + ); + if (!logsResponse.data) { + } else { + let zipData; + if (logsResponse.data instanceof ArrayBuffer) { + zipData = new Uint8Array(logsResponse.data); + } else if (logsResponse.data instanceof Uint8Array) { + zipData = logsResponse.data; + } else if ( + typeof Buffer !== "undefined" && + Buffer.isBuffer(logsResponse.data) + ) { + zipData = new Uint8Array( + logsResponse.data.buffer, + logsResponse.data.byteOffset, + logsResponse.data.byteLength, + ); + } else { + throw new Error("logsResponse.data is not a supported binary type"); + } + let files; + try { + files = unzipSync(zipData); + } catch (e) { + continue; + } + let found = false; + for (const [, fileData] of Object.entries(files)) { + let content; + try { + content = strFromU8(fileData); + } catch (e) { + continue; + } + if (typeof content !== "string" || !content) { + continue; + } + let extracted; + try { + extracted = extractCountsBlock(content); + } catch (e) { + continue; + } + if (extracted) { + stats = extracted; + found = true; + break; + } + } + } + } catch (e) { + if ( + e instanceof Error && + e.message && + e.message.includes("Server Error") + ) { + // skip + } + } + if (stats) { + results.push({ + run_number: run.run_number, + created_at: run.created_at, + stats, + }); + } + } + // 5. Return JSON + cachedData = { runs: results }; + lastFetch = Date.now(); + return cachedData; + } catch (err) { + return { error: true, message: String(err), stack: (err as any)?.stack }; + } +}); diff --git a/packages/app/server/routes/chart-old-api.get.ts b/packages/app/server/routes/chart-old-api.get.ts new file mode 100644 index 00000000..c15e20ea --- /dev/null +++ b/packages/app/server/routes/chart-old-api.get.ts @@ -0,0 +1,148 @@ +import { defineEventHandler, H3Event } from "h3"; +import { useOctokitInstallation } from "../utils/octokit"; +import { unzipSync, strFromU8 } from "fflate"; + +function extractCountsBlock(content: string): any | null { + const lines = content.split("\n"); + let startIdx = -1; + for (let i = 0; i < lines.length; i++) { + if (lines[i].includes("Counts: {")) { + startIdx = i; + break; + } + } + if (startIdx === -1) return null; + // Collect lines until closing } + const blockLines = []; + for (let i = startIdx; i < lines.length; i++) { + blockLines.push(lines[i]); + if (lines[i].trim().endsWith("}")) break; + } + // Join and clean up + let block = blockLines.join("\n"); + // Remove the leading 'Counts: ' and timestamps + block = block.replace(/.*Counts: /, ""); + block = block.replace(/^[^\{]*\{/, "{"); // Remove anything before first { + // Remove timestamps at the start of each line + block = block.replace(/^[0-9TZ\-:\.]+Z /gm, ""); + // Convert JS object to JSON (add quotes) + block = block.replace(/([a-zA-Z0-9_]+):/g, '"$1":'); + try { + return JSON.parse(block); + } catch (e) { + return null; + } +} + +let cachedData: any = null; +let lastFetch = 0; +const CACHE_DURATION = 7 * 24 * 60 * 60 * 1000; // 1 week in ms + +export default defineEventHandler(async (event: H3Event) => { + try { + if (cachedData && Date.now() - lastFetch < CACHE_DURATION) { + return cachedData; + } + const owner = "stackblitz-labs"; + const repo = "pkg.pr.new"; + const workflowId = "stats.yml"; + + const octokit = await useOctokitInstallation(event, owner, repo); + + const runs = await octokit.paginate(octokit.rest.actions.listWorkflowRuns, { + owner, + repo, + workflow_id: workflowId, + per_page: 100, + status: "success", + }); + + // Only process the latest 100 runs for performance + const latestRuns = runs.slice(0, 100); + + // 4. For each run, download logs, unzip, and extract Counts + const results = []; + for (const run of latestRuns) { + let stats = null; + try { + const logsResponse = await octokit.rest.actions.downloadWorkflowRunLogs( + { + owner, + repo, + run_id: run.id, + }, + ); + if (!logsResponse.data) { + } else { + let zipData; + if (logsResponse.data instanceof ArrayBuffer) { + zipData = new Uint8Array(logsResponse.data); + } else if (logsResponse.data instanceof Uint8Array) { + zipData = logsResponse.data; + } else if ( + typeof Buffer !== "undefined" && + Buffer.isBuffer(logsResponse.data) + ) { + zipData = new Uint8Array( + logsResponse.data.buffer, + logsResponse.data.byteOffset, + logsResponse.data.byteLength, + ); + } else { + throw new Error("logsResponse.data is not a supported binary type"); + } + let files; + try { + files = unzipSync(zipData); + } catch (e) { + continue; + } + let found = false; + for (const [, fileData] of Object.entries(files)) { + let content; + try { + content = strFromU8(fileData); + } catch (e) { + continue; + } + if (typeof content !== "string" || !content) { + continue; + } + let extracted; + try { + extracted = extractCountsBlock(content); + } catch (e) { + continue; + } + if (extracted) { + stats = extracted; + found = true; + break; + } + } + } + } catch (e) { + if ( + e instanceof Error && + e.message && + e.message.includes("Server Error") + ) { + // skip + } + } + if (stats) { + results.push({ + run_number: run.run_number, + created_at: run.created_at, + stats, + }); + } + } + // 5. Return JSON + cachedData = { runs: results }; + lastFetch = Date.now(); + return cachedData; + } catch (err) { + return { error: true, message: String(err), stack: (err as any)?.stack }; + } +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d63b37b7..2b5e3ccb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -101,9 +101,15 @@ importers: '@octokit/graphql': specifier: ^8.1.1 version: 8.1.1 + '@octokit/openapi-types': + specifier: ^25.1.0 + version: 25.1.0 '@octokit/plugin-paginate-rest': specifier: ^11.3.6 version: 11.3.6(@octokit/core@6.1.4) + '@octokit/rest': + specifier: ^22.0.0 + version: 22.0.0 '@octokit/webhooks': specifier: ^13.4.1 version: 13.4.1 @@ -113,6 +119,18 @@ importers: '@vueuse/nuxt': specifier: ^12.2.0 version: 12.5.0(magicast@0.3.5)(nuxt@3.15.3(@parcel/watcher@2.5.0)(@types/node@20.17.10)(db0@0.2.1)(eslint@8.57.1)(ioredis@5.4.2)(lightningcss@1.28.2)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.7.2)(vite@6.2.5(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1))(vue-tsc@2.1.10(typescript@5.7.2))(yaml@2.7.1))(typescript@5.7.2) + chart.js: + specifier: ^4.5.0 + version: 4.5.0 + chartjs-adapter-date-fns: + specifier: ^3.0.0 + version: 3.0.0(chart.js@4.5.0)(date-fns@4.1.0) + chartjs-plugin-rough: + specifier: ^0.2.0 + version: 0.2.0(chart.js@4.5.0)(roughjs@4.6.6) + fflate: + specifier: ^0.8.2 + version: 0.8.2 marked: specifier: ^15.0.4 version: 15.0.4 @@ -137,6 +155,9 @@ importers: vue: specifier: ^3.5.13 version: 3.5.13(typescript@5.7.2) + vue-chartjs: + specifier: ^5.3.2 + version: 5.3.2(chart.js@4.5.0)(vue@3.5.13(typescript@5.7.2)) vue-router: specifier: ^4.4.3 version: 4.5.0(vue@3.5.13(typescript@5.7.2)) @@ -146,7 +167,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: ^3.12.1 - version: 3.16.0(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/debug@4.1.12)(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1)) + version: 3.16.0(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1)) '@cloudflare/workers-types': specifier: ^4.20240512.0 version: 4.20241218.0 @@ -1676,6 +1697,9 @@ packages: '@jspm/core@2.1.0': resolution: {integrity: sha512-3sRl+pkyFY/kLmHl0cgHiFp2xEqErA8N3ECjMs7serSUBmoJ70lBa0PG5t0IM6WJgdZNyyI0R8YFfi5wM8+mzg==} + '@kurkle/color@0.3.4': + resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} + '@kwsites/file-exists@1.1.1': resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==} @@ -1881,6 +1905,10 @@ packages: resolution: {integrity: sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==} engines: {node: '>= 18'} + '@octokit/auth-token@6.0.0': + resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} + engines: {node: '>= 20'} + '@octokit/auth-unauthenticated@5.0.1': resolution: {integrity: sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==} engines: {node: '>= 18'} @@ -1905,6 +1933,10 @@ packages: resolution: {integrity: sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==} engines: {node: '>= 18'} + '@octokit/core@7.0.3': + resolution: {integrity: sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==} + engines: {node: '>= 20'} + '@octokit/endpoint@10.1.2': resolution: {integrity: sha512-XybpFv9Ms4hX5OCHMZqyODYqGTZ3H6K6Vva+M9LR7ib/xr1y1ZnlChYv9H680y77Vd/i/k+thXApeRASBQkzhA==} engines: {node: '>= 18'} @@ -1913,6 +1945,10 @@ packages: resolution: {integrity: sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==} engines: {node: '>= 18'} + '@octokit/endpoint@11.0.0': + resolution: {integrity: sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==} + engines: {node: '>= 20'} + '@octokit/endpoint@9.0.5': resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==} engines: {node: '>= 18'} @@ -1929,6 +1965,10 @@ packages: resolution: {integrity: sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==} engines: {node: '>= 18'} + '@octokit/graphql@9.0.1': + resolution: {integrity: sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==} + engines: {node: '>= 20'} + '@octokit/oauth-app@7.1.3': resolution: {integrity: sha512-EHXbOpBkSGVVGF1W+NLMmsnSsJRkcrnVmDKt0TQYRBb6xWfWzoi9sBD4DIqZ8jGhOWO/V8t4fqFyJ4vDQDn9bg==} engines: {node: '>= 18'} @@ -1958,6 +1998,9 @@ packages: '@octokit/openapi-types@24.2.0': resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} + '@octokit/openapi-types@25.1.0': + resolution: {integrity: sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==} + '@octokit/openapi-webhooks-types@10.4.0': resolution: {integrity: sha512-HMiF7FUiVBYfp8pPijMTkWuPELQB6XkPftrnSuK1C1YXaaq2+0ganiQkorEQfXTmhtwlgHJwXT6P8miVhIyjQA==} @@ -1982,12 +2025,24 @@ packages: peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-paginate-rest@13.1.1': + resolution: {integrity: sha512-q9iQGlZlxAVNRN2jDNskJW/Cafy7/XE52wjZ5TTvyhyOD904Cvx//DNyoO3J/MXJ0ve3rPoNWKEg5iZrisQSuw==} + engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' + '@octokit/plugin-paginate-rest@9.2.1': resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' + '@octokit/plugin-request-log@6.0.0': + resolution: {integrity: sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==} + engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' + '@octokit/plugin-rest-endpoint-methods@10.4.1': resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} engines: {node: '>= 18'} @@ -2000,6 +2055,12 @@ packages: peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-rest-endpoint-methods@16.0.0': + resolution: {integrity: sha512-kJVUQk6/dx/gRNLWUnAWKFs1kVPn5O5CYZyssyEoNYaFedqZxsfYs7DwI3d67hGz4qOwaJ1dpm07hOAD1BXx6g==} + engines: {node: '>= 20'} + peerDependencies: + '@octokit/core': '>=6' + '@octokit/plugin-retry@7.2.0': resolution: {integrity: sha512-psMbEYb/Fh+V+ZaFo8J16QiFz4sVTv3GntCSU+hYqzHiMdc3P+hhHLVv+dJt0PGIPAGoIA5u+J2DCJdK6lEPsQ==} engines: {node: '>= 18'} @@ -2024,6 +2085,14 @@ packages: resolution: {integrity: sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==} engines: {node: '>= 18'} + '@octokit/request-error@7.0.0': + resolution: {integrity: sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==} + engines: {node: '>= 20'} + + '@octokit/request@10.0.3': + resolution: {integrity: sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==} + engines: {node: '>= 20'} + '@octokit/request@8.4.0': resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} engines: {node: '>= 18'} @@ -2036,6 +2105,10 @@ packages: resolution: {integrity: sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==} engines: {node: '>= 18'} + '@octokit/rest@22.0.0': + resolution: {integrity: sha512-z6tmTu9BTnw51jYGulxrlernpsQYXpui1RK21vmXn8yF5bp6iX16yfTtJYGK5Mh1qDkvDOmp2n8sRMcQmR8jiA==} + engines: {node: '>= 20'} + '@octokit/types@12.6.0': resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} @@ -2045,6 +2118,9 @@ packages: '@octokit/types@13.6.2': resolution: {integrity: sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==} + '@octokit/types@14.1.0': + resolution: {integrity: sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==} + '@octokit/webhooks-methods@5.1.0': resolution: {integrity: sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ==} engines: {node: '>= 18'} @@ -3324,6 +3400,9 @@ packages: before-after-hook@3.0.2: resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + before-after-hook@4.0.0: + resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -3491,6 +3570,22 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + chart.js@4.5.0: + resolution: {integrity: sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==} + engines: {pnpm: '>=8'} + + chartjs-adapter-date-fns@3.0.0: + resolution: {integrity: sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==} + peerDependencies: + chart.js: '>=2.8.0' + date-fns: '>=2.0.0' + + chartjs-plugin-rough@0.2.0: + resolution: {integrity: sha512-9BMkqr9btzwW7n+a1ognV44XmarBDdOMnSEpdudAcPzovQWAUqFibgwIZYLAb4D3Er1VBwCPdf61YC9HKGTi8w==} + peerDependencies: + chart.js: '>= 2.7.0 < 3' + roughjs: ^2.0.1 + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -4521,6 +4616,9 @@ packages: fast-content-type-parse@2.0.1: resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} + fast-content-type-parse@3.0.0: + resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -4571,6 +4669,9 @@ packages: picomatch: optional: true + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -4824,6 +4925,9 @@ packages: h3@1.15.3: resolution: {integrity: sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ==} + hachure-fill@0.5.2: + resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -6137,6 +6241,9 @@ packages: path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-data-parser@0.1.0: + resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -6223,6 +6330,12 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} + points-on-curve@0.2.0: + resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} + + points-on-path@0.2.1: + resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -6779,6 +6892,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + roughjs@4.6.6: + resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} engines: {node: '>=18'} @@ -7838,6 +7954,12 @@ packages: vue-bundle-renderer@2.1.1: resolution: {integrity: sha512-+qALLI5cQncuetYOXp4yScwYvqh8c6SMXee3B+M7oTZxOgtESP0l4j/fXdEJoZ+EdMxkGWIj+aSEyjXkOdmd7g==} + vue-chartjs@5.3.2: + resolution: {integrity: sha512-NrkbRRoYshbXbWqJkTN6InoDVwVb90C0R7eAVgMWcB9dPikbruaOoTFjFYHE/+tNPdIe6qdLCDjfjPHQ0fw4jw==} + peerDependencies: + chart.js: ^4.1.1 + vue: ^3.0.0-0 || ^2.7.0 + vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} engines: {node: '>=12'} @@ -8122,7 +8244,7 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@antfu/eslint-config@3.16.0(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/debug@4.1.12)(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1))': + '@antfu/eslint-config@3.16.0(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(@vue/compiler-sfc@3.5.13)(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1))': dependencies: '@antfu/install-pkg': 1.0.0 '@clack/prompts': 0.9.1 @@ -8131,7 +8253,7 @@ snapshots: '@stylistic/eslint-plugin': 2.13.0(eslint@8.57.1)(typescript@5.7.2) '@typescript-eslint/eslint-plugin': 8.29.0(@typescript-eslint/parser@8.29.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2) '@typescript-eslint/parser': 8.29.0(eslint@8.57.1)(typescript@5.7.2) - '@vitest/eslint-plugin': 1.1.39(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/debug@4.1.12)(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1)) + '@vitest/eslint-plugin': 1.1.39(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1)) eslint: 8.57.1 eslint-config-flat-gitignore: 1.0.1(eslint@8.57.1) eslint-flat-config-utils: 1.1.0 @@ -9230,6 +9352,8 @@ snapshots: '@jspm/core@2.1.0': {} + '@kurkle/color@0.3.4': {} + '@kwsites/file-exists@1.1.1': dependencies: debug: 4.4.0(supports-color@9.4.0) @@ -9314,7 +9438,7 @@ snapshots: semver: 7.7.1 std-env: 3.9.0 tinyexec: 1.0.1 - ufo: 1.5.4 + ufo: 1.6.1 youch: 4.1.0-beta.6 transitivePeerDependencies: - magicast @@ -9474,7 +9598,7 @@ snapshots: pathe: 1.1.2 sirv: 3.0.0 tinyglobby: 0.2.12 - ufo: 1.5.4 + ufo: 1.6.1 unifont: 0.1.7 unplugin: 2.2.2 unstorage: 1.16.0(db0@0.2.1)(ioredis@5.4.2) @@ -9545,7 +9669,7 @@ snapshots: scule: 1.3.0 semver: 7.7.1 std-env: 3.9.0 - ufo: 1.5.4 + ufo: 1.6.1 unctx: 2.4.1 unimport: 4.1.3 untyped: 1.5.2 @@ -9591,7 +9715,7 @@ snapshots: pkg-types: 1.3.1 scule: 1.3.0 std-env: 3.9.0 - ufo: 1.5.4 + ufo: 1.6.1 uncrypto: 0.1.3 unimport: 3.14.5(rollup@4.29.1) untyped: 1.5.2 @@ -9736,7 +9860,7 @@ snapshots: postcss: 8.5.3 rollup-plugin-visualizer: 5.14.0(rollup@4.29.1) std-env: 3.9.0 - ufo: 1.5.4 + ufo: 1.6.1 unenv: 1.10.0 unplugin: 2.2.2 vite: 6.2.5(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1) @@ -9932,6 +10056,8 @@ snapshots: '@octokit/auth-token@5.1.1': {} + '@octokit/auth-token@6.0.0': {} + '@octokit/auth-unauthenticated@5.0.1': dependencies: '@octokit/request-error': 5.1.0 @@ -9977,6 +10103,16 @@ snapshots: before-after-hook: 3.0.2 universal-user-agent: 7.0.2 + '@octokit/core@7.0.3': + dependencies: + '@octokit/auth-token': 6.0.0 + '@octokit/graphql': 9.0.1 + '@octokit/request': 10.0.3 + '@octokit/request-error': 7.0.0 + '@octokit/types': 14.1.0 + before-after-hook: 4.0.0 + universal-user-agent: 7.0.2 + '@octokit/endpoint@10.1.2': dependencies: '@octokit/types': 13.6.2 @@ -9987,6 +10123,11 @@ snapshots: '@octokit/types': 13.10.0 universal-user-agent: 7.0.2 + '@octokit/endpoint@11.0.0': + dependencies: + '@octokit/types': 14.1.0 + universal-user-agent: 7.0.2 + '@octokit/endpoint@9.0.5': dependencies: '@octokit/types': 13.6.2 @@ -10010,6 +10151,12 @@ snapshots: '@octokit/types': 13.10.0 universal-user-agent: 7.0.2 + '@octokit/graphql@9.0.1': + dependencies: + '@octokit/request': 10.0.3 + '@octokit/types': 14.1.0 + universal-user-agent: 7.0.2 + '@octokit/oauth-app@7.1.3': dependencies: '@octokit/auth-oauth-app': 8.1.1 @@ -10054,6 +10201,8 @@ snapshots: '@octokit/openapi-types@24.2.0': {} + '@octokit/openapi-types@25.1.0': {} + '@octokit/openapi-webhooks-types@10.4.0': {} '@octokit/openapi-webhooks-types@8.5.1': {} @@ -10077,11 +10226,20 @@ snapshots: '@octokit/core': 6.1.4 '@octokit/types': 13.10.0 + '@octokit/plugin-paginate-rest@13.1.1(@octokit/core@7.0.3)': + dependencies: + '@octokit/core': 7.0.3 + '@octokit/types': 14.1.0 + '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.2.0)': dependencies: '@octokit/core': 5.2.0 '@octokit/types': 12.6.0 + '@octokit/plugin-request-log@6.0.0(@octokit/core@7.0.3)': + dependencies: + '@octokit/core': 7.0.3 + '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.0)': dependencies: '@octokit/core': 5.2.0 @@ -10092,6 +10250,11 @@ snapshots: '@octokit/core': 6.1.4 '@octokit/types': 13.10.0 + '@octokit/plugin-rest-endpoint-methods@16.0.0(@octokit/core@7.0.3)': + dependencies: + '@octokit/core': 7.0.3 + '@octokit/types': 14.1.0 + '@octokit/plugin-retry@7.2.0(@octokit/core@6.1.4)': dependencies: '@octokit/core': 6.1.4 @@ -10119,6 +10282,18 @@ snapshots: dependencies: '@octokit/types': 13.10.0 + '@octokit/request-error@7.0.0': + dependencies: + '@octokit/types': 14.1.0 + + '@octokit/request@10.0.3': + dependencies: + '@octokit/endpoint': 11.0.0 + '@octokit/request-error': 7.0.0 + '@octokit/types': 14.1.0 + fast-content-type-parse: 3.0.0 + universal-user-agent: 7.0.2 + '@octokit/request@8.4.0': dependencies: '@octokit/endpoint': 9.0.5 @@ -10141,6 +10316,13 @@ snapshots: fast-content-type-parse: 2.0.1 universal-user-agent: 7.0.2 + '@octokit/rest@22.0.0': + dependencies: + '@octokit/core': 7.0.3 + '@octokit/plugin-paginate-rest': 13.1.1(@octokit/core@7.0.3) + '@octokit/plugin-request-log': 6.0.0(@octokit/core@7.0.3) + '@octokit/plugin-rest-endpoint-methods': 16.0.0(@octokit/core@7.0.3) + '@octokit/types@12.6.0': dependencies: '@octokit/openapi-types': 20.0.0 @@ -10153,6 +10335,10 @@ snapshots: dependencies: '@octokit/openapi-types': 22.2.0 + '@octokit/types@14.1.0': + dependencies: + '@octokit/openapi-types': 25.1.0 + '@octokit/webhooks-methods@5.1.0': {} '@octokit/webhooks-methods@5.1.1': {} @@ -11030,13 +11216,13 @@ snapshots: publint: 0.2.12 semver: 7.6.3 - '@vitest/eslint-plugin@1.1.39(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/debug@4.1.12)(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1))': + '@vitest/eslint-plugin@1.1.39(@typescript-eslint/utils@8.29.0(eslint@8.57.1)(typescript@5.7.2))(eslint@8.57.1)(typescript@5.7.2)(vitest@3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1))': dependencies: '@typescript-eslint/utils': 8.29.0(eslint@8.57.1)(typescript@5.7.2) eslint: 8.57.1 optionalDependencies: typescript: 5.7.2 - vitest: 3.1.1(@types/debug@4.1.12)(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1) + vitest: 3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1) '@vitest/expect@3.1.1': dependencies: @@ -11568,6 +11754,8 @@ snapshots: before-after-hook@3.0.2: {} + before-after-hook@4.0.0: {} + binary-extensions@2.3.0: {} bindings@1.5.0: @@ -11766,6 +11954,20 @@ snapshots: character-reference-invalid@2.0.1: {} + chart.js@4.5.0: + dependencies: + '@kurkle/color': 0.3.4 + + chartjs-adapter-date-fns@3.0.0(chart.js@4.5.0)(date-fns@4.1.0): + dependencies: + chart.js: 4.5.0 + date-fns: 4.1.0 + + chartjs-plugin-rough@0.2.0(chart.js@4.5.0)(roughjs@4.6.6): + dependencies: + chart.js: 4.5.0 + roughjs: 4.6.6 + check-error@2.1.1: {} chokidar@3.6.0: @@ -13053,10 +13255,12 @@ snapshots: enhanced-resolve: 5.18.0 mlly: 1.7.4 pathe: 1.1.2 - ufo: 1.5.4 + ufo: 1.6.1 fast-content-type-parse@2.0.1: {} + fast-content-type-parse@3.0.0: {} + fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -13104,6 +13308,8 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fflate@0.8.2: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -13167,7 +13373,7 @@ snapshots: magic-regexp: 0.8.0 magic-string: 0.30.17 pathe: 1.1.2 - ufo: 1.5.4 + ufo: 1.6.1 unplugin: 1.16.0 transitivePeerDependencies: - encoding @@ -13418,7 +13624,7 @@ snapshots: iron-webcrypto: 1.2.1 ohash: 1.1.4 radix3: 1.1.2(patch_hash=gsdwrxpd7rn5ueaa55ufykpidm) - ufo: 1.5.4 + ufo: 1.6.1 uncrypto: 0.1.3 unenv: 1.10.0 @@ -13431,7 +13637,7 @@ snapshots: iron-webcrypto: 1.2.1 node-mock-http: 1.0.0 radix3: 1.1.2(patch_hash=gsdwrxpd7rn5ueaa55ufykpidm) - ufo: 1.5.4 + ufo: 1.6.1 uncrypto: 0.1.3 h3@1.15.3: @@ -13446,6 +13652,8 @@ snapshots: ufo: 1.6.1 uncrypto: 0.1.3 + hachure-fill@0.5.2: {} + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -14088,7 +14296,7 @@ snapshots: node-forge: 1.3.1 pathe: 1.1.2 std-env: 3.8.0 - ufo: 1.5.4 + ufo: 1.6.1 untun: 0.1.3 uqr: 0.1.2 @@ -14152,7 +14360,7 @@ snapshots: mlly: 1.7.4 regexp-tree: 0.1.27 type-level-regexp: 0.1.17 - ufo: 1.5.4 + ufo: 1.6.1 unplugin: 1.16.0 magic-string-ast@0.7.1: @@ -14738,7 +14946,7 @@ snapshots: serve-placeholder: 2.0.2 serve-static: 1.16.2 std-env: 3.8.0 - ufo: 1.5.4 + ufo: 1.6.1 uncrypto: 0.1.3 unctx: 2.4.1 unenv: 1.10.0 @@ -14974,7 +15182,7 @@ snapshots: execa: 8.0.1 pathe: 1.1.2 pkg-types: 1.3.1 - ufo: 1.5.4 + ufo: 1.6.1 nypm@0.4.1: dependencies: @@ -14983,7 +15191,7 @@ snapshots: pathe: 1.1.2 pkg-types: 1.3.1 tinyexec: 0.3.2 - ufo: 1.5.4 + ufo: 1.6.1 nypm@0.5.4: dependencies: @@ -14992,7 +15200,7 @@ snapshots: pathe: 2.0.3 pkg-types: 1.3.1 tinyexec: 0.3.2 - ufo: 1.5.4 + ufo: 1.6.1 nypm@0.6.0: dependencies: @@ -15056,7 +15264,7 @@ snapshots: dependencies: destr: 2.0.3 node-fetch-native: 1.6.4 - ufo: 1.5.4 + ufo: 1.6.1 ohash@1.1.4: {} @@ -15237,6 +15445,8 @@ snapshots: path-browserify@1.0.1: {} + path-data-parser@0.1.0: {} + path-exists@4.0.0: {} path-exists@5.0.0: {} @@ -15300,6 +15510,13 @@ snapshots: pluralize@8.0.0: {} + points-on-curve@0.2.0: {} + + points-on-path@0.2.1: + dependencies: + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + possible-typed-array-names@1.0.0: {} postcss-calc@10.0.2(postcss@8.5.3): @@ -15961,6 +16178,13 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.39.0 fsevents: 2.3.3 + roughjs@4.6.6: + dependencies: + hachure-fill: 0.5.2 + path-data-parser: 0.1.0 + points-on-curve: 0.2.0 + points-on-path: 0.2.1 + run-applescript@7.0.0: {} run-parallel@1.2.0: @@ -16691,7 +16915,7 @@ snapshots: mlly: 1.7.4 ohash: 1.1.4 pathe: 1.1.2 - ufo: 1.5.4 + ufo: 1.6.1 unhead@1.11.14: dependencies: @@ -17140,6 +17364,45 @@ snapshots: - tsx - yaml + vitest@3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1): + dependencies: + '@vitest/expect': 3.1.1 + '@vitest/mocker': 3.1.1(vite@6.2.5(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1)) + '@vitest/pretty-format': 3.1.1 + '@vitest/runner': 3.1.1 + '@vitest/snapshot': 3.1.1 + '@vitest/spy': 3.1.1 + '@vitest/utils': 3.1.1 + chai: 5.2.0 + debug: 4.4.0(supports-color@9.4.0) + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.5(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1) + vite-node: 3.1.1(@types/node@20.17.10)(jiti@2.4.2)(lightningcss@1.28.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.17.10 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + optional: true + vscode-jsonrpc@6.0.0: {} vscode-languageclient@7.0.0: @@ -17165,7 +17428,12 @@ snapshots: vue-bundle-renderer@2.1.1: dependencies: - ufo: 1.5.4 + ufo: 1.6.1 + + vue-chartjs@5.3.2(chart.js@4.5.0)(vue@3.5.13(typescript@5.7.2)): + dependencies: + chart.js: 4.5.0 + vue: 3.5.13(typescript@5.7.2) vue-demi@0.14.10(vue@3.5.13(typescript@5.7.2)): dependencies: