diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..108e3da
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,4 @@
+# GitHub Personal Access Token (optional, but recommended for higher rate limits)
+# Generate one at: https://github.com/settings/tokens
+# No scopes are needed for public data
+GITHUB_TOKEN=your_github_token_here
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..7d000a1
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,28 @@
+## Description
+
+[//]: # "Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context."
+
+## Type of Change
+
+[//]: # "Please select one"
+
+- [ ] Feature
+- [ ] Bugfix
+- [ ] Refactor
+- [ ] Documentation
+- [ ] Other
+
+## Checklist
+
+[//]: # "Please check all that apply"
+
+- [ ] Manually tested by running `pnpm dev` and viewing all pages
+- [ ] It can build a prod build with `pnpm build`
+- [ ] Documentation and comments added
+- [ ] No console warnings or errors
+- [ ] No ESLint warnings or errors
+- [ ] No prettier warnings or errors
+
+## Supplementary Information
+
+[//]: # "Any other information that is important to this PR, such as screenshots of a UI change"
diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml
new file mode 100644
index 0000000..25ab60e
--- /dev/null
+++ b/.github/workflows/code-quality.yml
@@ -0,0 +1,37 @@
+name: Code Quality
+
+on:
+ pull_request:
+ branches: [ main ]
+ push:
+ branches: [ main ]
+
+jobs:
+ lint-and-format:
+ name: Lint & Format
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # actions/checkout@v6
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # pnpm/action-setup@v4
+ with:
+ version: 10
+
+ - name: Setup Node.js
+ uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # actions/setup-node@v6
+ with:
+ node-version: 24
+ cache: "pnpm"
+
+ - name: Install dependencies
+ run: pnpm install
+
+ # Takes less than eslint, so we run it first
+ - name: Run Prettier check
+ run: pnpm format:check
+
+ - name: Run ESLint
+ run: pnpm lint:check
diff --git a/.gitignore b/.gitignore
index 9a5aced..ab7b419 100644
--- a/.gitignore
+++ b/.gitignore
@@ -137,3 +137,7 @@ dist
# Vite logs files
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
+
+# Sandbox test outputs
+sandbox/output-*.svg
+sandbox/output-*-languages-*.svg
diff --git a/.prettierc.json b/.prettierc.json
new file mode 100644
index 0000000..5731c95
--- /dev/null
+++ b/.prettierc.json
@@ -0,0 +1,10 @@
+{
+ "semi": false,
+ "singleQuote": false,
+ "tabWidth": 2,
+ "trailingComma": "es5",
+ "printWidth": 100,
+ "bracketSpacing": true,
+ "arrowParens": "avoid",
+ "endOfLine": "lf"
+}
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..a4db8df
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,5 @@
+package.json
+package-lock.json
+pnpm-lock.yaml
+README.md
+.github/**
diff --git a/README.md b/README.md
index 217252d..eae036d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,74 @@
-# github-flex
-Flex your GitHub stats with customizable SVG badges for your profile. Because your GitHub profile deserves to look as good as your code...right?!
+# GitHub Flex
+
+Flex your GitHub stats with customizable SVG badges for your profile. Because your GitHub profile deserves to look as
+good as your code...right?!
+
+## ๐ Quick Start
+
+Use the following Markdown snippets to add your GitHub stats, languages, or specific repo info to your profile README:
+
+```markdown
+
+
+
+```
+
+## ๐ Available Endpoints
+
+### `/api/stats`
+
+**Parameters:**
+
+- `username` (required)
+- `theme` - `default`, `dark`, `radical`, `merko`, `gruvbox`, `tokyonight`
+- `hide_border` - `true` or `false`
+- `hide_title` - `true` or `false`
+
+### `/api/languages`
+
+**Parameters:**
+
+- `username` (required)
+- `theme` - same as above
+- `langs_count` - number (default: 5)
+- `exclude` - comma-separated languages to exclude (e.g., `HTML,CSS`)
+- `hide_border`, `hide_title`
+
+### `/api/repo`
+
+**Parameters:**
+
+- `username` (required)
+- `repo` (required)
+- `theme`, `hide_border`
+
+## ๐ป Local Development
+
+```bash
+# Install
+pnpm install
+# or: npm install
+
+# Build
+pnpm build
+# or: npm run build
+
+# Run with Vercel CLI
+vercel dev
+
+# Test without Vercel CLI
+node sandbox/test-stats.js torvalds
+node sandbox/test-languages.js torvalds 8
+node sandbox/test-svg.js torvalds dark
+node sandbox/test-languages-svg.js torvalds dark 8
+```
+
+## โ๏ธ Deploy to Vercel
+
+1. Fork this repo
+2. Connect to [Vercel](https://vercel.com)
+3. (Optional) Add `GITHUB_TOKEN` env variable for higher rate limits
+
+## ๐ License
+
+This project is licensed under the [MIT License](LICENSE).
diff --git a/api/languages.ts b/api/languages.ts
new file mode 100644
index 0000000..3ed990b
--- /dev/null
+++ b/api/languages.ts
@@ -0,0 +1,108 @@
+import { VercelRequest, VercelResponse } from "@vercel/node";
+import { fetchLanguageStats, getTopLanguages } from "../lib/languages.js";
+import { generateCard, generateLanguageItem } from "../lib/card.js";
+import { ThemeName } from "../lib/types.js";
+import { themes } from "../lib/themes.js";
+
+/**
+ * API handler to generate a GitHub languages badge.
+ * Accepts query parameters:
+ * - username (required): GitHub username
+ * - theme (optional): Card theme (default: "default")
+ * - hide_border (optional): Whether to hide the card border (true/false)
+ * - hide_title (optional): Whether to hide the card title (true/false)
+ * - langs_count (optional): Number of top languages to display (default: 5)
+ * - exclude (optional): Comma-separated list of languages to exclude (e.g., "HTML,CSS")
+ */
+export default async function handler(req: VercelRequest, res: VercelResponse) {
+ const {
+ username,
+ theme = ThemeName.Default,
+ hide_border,
+ hide_title,
+ langs_count = "5",
+ exclude,
+ } = req.query;
+
+ // Validate username
+ if (!username || typeof username !== "string") {
+ return res.status(400).json({ error: "Username is required" });
+ }
+
+ // Validate theme
+ const selectedTheme =
+ typeof theme === "string" &&
+ Object.values(ThemeName).includes(theme as ThemeName)
+ ? (theme as ThemeName)
+ : ThemeName.Default;
+ const langsCount = parseInt(
+ typeof langs_count === "string" ? langs_count : "5",
+ 10,
+ );
+
+ try {
+ // Get GitHub token from environment variable
+ const githubToken = process.env.GITHUB_TOKEN;
+
+ // Get excluded languages
+ const excludeParam = typeof exclude === "string" ? exclude : undefined;
+
+ // Fetch language stats
+ const stats = await fetchLanguageStats(username, githubToken, excludeParam);
+ const topLanguages = getTopLanguages(stats, langsCount);
+
+ if (topLanguages.length === 0) {
+ throw new Error("No languages found");
+ }
+
+ // Get theme colors
+ const colors = themes[selectedTheme];
+
+ // Generate language items with playful card styling
+ const languageItems = topLanguages
+ .map((lang, index) =>
+ generateLanguageItem(
+ lang.name,
+ lang.percent,
+ index,
+ colors.icon,
+ colors.border,
+ ),
+ )
+ .join("");
+
+ // Calculate card height based on number of languages (adjusted for new layout)
+ const cardHeight = 90 + topLanguages.length * 50;
+
+ // Generate the card
+ const svg = generateCard(languageItems, {
+ title: hide_title === "true" ? "" : "Most Used Languages",
+ width: 450,
+ height: cardHeight,
+ theme: selectedTheme,
+ hideBorder: hide_border === "true",
+ });
+
+ // Set cache headers (cache for 4 hours)
+ res.setHeader("Content-Type", "image/svg+xml");
+ res.setHeader("Cache-Control", "public, max-age=14400");
+
+ return res.status(200).send(svg);
+ } catch (error) {
+ console.error("Error generating language badge:", error);
+
+ // Return error SVG
+ const errorSvg = generateCard(
+ `Failed to fetch language stats`,
+ {
+ title: "Most Used Languages",
+ width: 450,
+ height: 120,
+ theme: selectedTheme,
+ },
+ );
+
+ res.setHeader("Content-Type", "image/svg+xml");
+ return res.status(500).send(errorSvg);
+ }
+}
diff --git a/api/repo.ts b/api/repo.ts
new file mode 100644
index 0000000..944d4e4
--- /dev/null
+++ b/api/repo.ts
@@ -0,0 +1,147 @@
+import { VercelRequest, VercelResponse } from "@vercel/node";
+import { generateCard, escapeXml } from "../lib/card.js";
+import { ThemeName, RepoData, GitHubRepoResponse } from "../lib/types.js";
+import { themes } from "../lib/themes.js";
+
+async function fetchRepoStats(
+ owner: string,
+ repo: string,
+ token?: string,
+): Promise {
+ const headers: HeadersInit = {
+ Accept: "application/vnd.github+json",
+ };
+
+ if (token) {
+ headers["Authorization"] = `Bearer ${token}`;
+ }
+
+ const response = await fetch(
+ `https://api.github.com/repos/${owner}/${repo}`,
+ { headers },
+ );
+
+ if (!response.ok) {
+ throw new Error(`GitHub API error: ${response.status}`);
+ }
+
+ const data = (await response.json()) as GitHubRepoResponse;
+
+ return {
+ name: data.name,
+ description: data.description || "No description provided",
+ stars: data.stargazers_count,
+ forks: data.forks_count,
+ language: data.language || "Unknown",
+ openIssues: data.open_issues_count,
+ };
+}
+
+/**
+ * API handler to generate a GitHub repository stats card.
+ * Accepts query parameters:
+ * - username (required): GitHub username
+ * - repo (required): Repository name
+ * - theme (optional): Card theme (default: "default")
+ * - hide_border (optional): Whether to hide the card border (true/false)
+ */
+export default async function handler(req: VercelRequest, res: VercelResponse) {
+ const { username, repo, theme = ThemeName.Default, hide_border } = req.query;
+
+ // Validate parameters
+ if (!username || typeof username !== "string") {
+ return res.status(400).json({ error: "Username is required" });
+ }
+
+ if (!repo || typeof repo !== "string") {
+ return res.status(400).json({ error: "Repository name is required" });
+ }
+
+ // Validate theme
+ const selectedTheme =
+ typeof theme === "string" &&
+ Object.values(ThemeName).includes(theme as ThemeName)
+ ? (theme as ThemeName)
+ : ThemeName.Default;
+
+ try {
+ // Get GitHub token from environment variable
+ const githubToken = process.env.GITHUB_TOKEN;
+
+ // Fetch repo stats
+ const repoData = await fetchRepoStats(username, repo, githubToken);
+
+ // Get theme colors
+ const colors = themes[selectedTheme];
+
+ // Generate repo card content
+ const truncatedDesc = repoData.description.substring(0, 60);
+ const content = `
+
+
+ ${escapeXml(truncatedDesc)}${repoData.description.length > 60 ? "..." : ""}
+
+
+
+
+
+ ${repoData.stars.toLocaleString()} stars
+
+
+
+
+ ${repoData.forks.toLocaleString()} forks
+
+
+
+
+ ${escapeXml(repoData.language)}
+
+
+
+
+ ${repoData.openIssues.toLocaleString()} open issues
+
+ `;
+
+ // Generate the card (title will be escaped inside generateCard)
+ const svg = generateCard(content, {
+ title: repoData.name,
+ width: 450,
+ height: 210,
+ theme: selectedTheme,
+ hideBorder: hide_border === "true",
+ });
+
+ // Set cache headers (cache for 4 hours)
+ res.setHeader("Content-Type", "image/svg+xml");
+ res.setHeader("Cache-Control", "public, max-age=14400");
+
+ return res.status(200).send(svg);
+ } catch (error) {
+ console.error("Error generating repo card:", error);
+
+ // Return error SVG
+ const errorSvg = generateCard(
+ `Failed to fetch repository stats`,
+ {
+ title: "Repository Stats",
+ width: 450,
+ height: 120,
+ theme: selectedTheme,
+ },
+ );
+
+ res.setHeader("Content-Type", "image/svg+xml");
+ return res.status(500).send(errorSvg);
+ }
+}
diff --git a/api/stats.ts b/api/stats.ts
new file mode 100644
index 0000000..bfcb993
--- /dev/null
+++ b/api/stats.ts
@@ -0,0 +1,81 @@
+import { VercelRequest, VercelResponse } from "@vercel/node";
+import { fetchGitHubStats } from "../lib/github.js";
+import { generateCard, generateStatItem } from "../lib/card.js";
+import { ThemeName } from "../lib/types.js";
+
+/**
+ * API handler to generate a GitHub stats badge.
+ * Accepts query parameters:
+ * - username (required): GitHub username
+ * - theme (optional): Card theme (default: "default")
+ * - hide_border (optional): Whether to hide the card border (true/false)
+ * - hide_title (optional): Whether to hide the card title (true/false)
+ */
+export default async function handler(req: VercelRequest, res: VercelResponse) {
+ const {
+ username,
+ theme = ThemeName.Default,
+ hide_border,
+ hide_title,
+ } = req.query;
+
+ // Validate username
+ if (!username || typeof username !== "string") {
+ return res.status(400).json({ error: "Username is required" });
+ }
+
+ // Validate theme
+ const selectedTheme =
+ typeof theme === "string" &&
+ Object.values(ThemeName).includes(theme as ThemeName)
+ ? (theme as ThemeName)
+ : ThemeName.Default;
+
+ try {
+ // Get GitHub token from environment variable (optional but recommended for higher rate limits)
+ const githubToken = process.env.GITHUB_TOKEN;
+
+ // Fetch GitHub stats
+ const stats = await fetchGitHubStats(username, githubToken);
+
+ // Generate stat items
+ const statItems = [
+ generateStatItem("Total Stars", stats.totalStars.toLocaleString(), 0),
+ generateStatItem("Total Commits", stats.totalCommits.toLocaleString(), 1),
+ generateStatItem("Total PRs", stats.totalPRs.toLocaleString(), 2),
+ generateStatItem("Total Issues", stats.totalIssues.toLocaleString(), 3),
+ generateStatItem("Total Repos", stats.contributedTo.toLocaleString(), 4),
+ ].join("");
+
+ // Generate the card with adjusted dimensions for 2-column layout
+ const svg = generateCard(statItems, {
+ title: hide_title === "true" ? "" : `${username}'s GitHub Stats`,
+ width: 500,
+ height: 240,
+ theme: selectedTheme,
+ hideBorder: hide_border === "true",
+ });
+
+ // Set cache headers (cache for 4 hours)
+ res.setHeader("Content-Type", "image/svg+xml");
+ res.setHeader("Cache-Control", "public, max-age=14400");
+
+ return res.status(200).send(svg);
+ } catch (error) {
+ console.error("Error generating stats badge:", error);
+
+ // Return error SVG
+ const errorSvg = generateCard(
+ generateStatItem("Error", "Failed to fetch stats", 0, false),
+ {
+ title: "GitHub Stats",
+ width: 495,
+ height: 120,
+ theme: selectedTheme,
+ },
+ );
+
+ res.setHeader("Content-Type", "image/svg+xml");
+ return res.status(500).send(errorSvg);
+ }
+}
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..dab5697
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,85 @@
+import js from "@eslint/js";
+import tsPlugin from "@typescript-eslint/eslint-plugin";
+import tsParser from "@typescript-eslint/parser";
+import globals from "globals";
+
+export default [
+ // Ignore patterns
+ {
+ ignores: [
+ "node_modules/**",
+ "dist/**",
+ "sandbox/output-*.svg",
+ ".vercel/**",
+ ".github/**",
+ ],
+ },
+
+ // JavaScript files (sandbox scripts)
+ {
+ files: ["sandbox/**/*.js"],
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: "module",
+ globals: {
+ ...globals.node,
+ },
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ "no-unused-vars": "warn",
+ "no-console": "off", // Allow console in sandbox scripts
+ },
+ },
+
+ // TypeScript files (lib and api)
+ {
+ files: ["lib/**/*.ts", "api/**/*.ts"],
+ languageOptions: {
+ parser: tsParser,
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: "module",
+ project: "./tsconfig.json",
+ },
+ globals: {
+ ...globals.node,
+ },
+ },
+ plugins: {
+ "@typescript-eslint": tsPlugin,
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ ...tsPlugin.configs.recommended.rules,
+
+ // TypeScript specific rules
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ {
+ argsIgnorePattern: "^_",
+ varsIgnorePattern: "^_",
+ },
+ ],
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off",
+ "@typescript-eslint/no-explicit-any": "warn",
+ "@typescript-eslint/no-non-null-assertion": "warn",
+
+ // General rules
+ "no-console": ["warn", { allow: ["warn", "error"] }],
+ "prefer-const": "error",
+ "no-var": "error",
+ eqeqeq: ["error", "always"],
+ curly: ["error", "all"],
+ },
+ },
+
+ // Vercel serverless functions
+ {
+ files: ["api/**/*.ts"],
+ rules: {
+ "no-console": "off", // Allow console in serverless functions for logging
+ },
+ },
+];
diff --git a/lib/card.ts b/lib/card.ts
new file mode 100644
index 0000000..66e73b8
--- /dev/null
+++ b/lib/card.ts
@@ -0,0 +1,240 @@
+/**
+ * Card generation utilities for GitHub Flex badges
+ */
+
+import { CardOptions, ThemeName } from "./types.js";
+import { themes } from "./themes.js";
+
+/**
+ * Generates an SVG card wrapper
+ */
+export function generateCard(content: string, options: CardOptions): string {
+ const {
+ title,
+ width = 500,
+ height = 200,
+ theme = ThemeName.Default,
+ borderRadius = 4.5,
+ hideBorder = false,
+ } = options;
+
+ const colors = themes[theme];
+
+ // Hand-drawn sketch effect using SVG filter
+ const sketchFilter = `
+
+
+
+
+ `;
+
+ return `
+
+ `;
+}
+
+/**
+ * Gets the appropriate icon SVG for a given stat type
+ */
+function getStatIcon(label: string): string {
+ const icons: Record = {
+ star: ``,
+ commits: ``,
+ prs: ``,
+ issues: ``,
+ contribs: ``,
+ };
+
+ const iconMap: Record = {
+ "Total Stars": icons.star,
+ "Total Commits": icons.commits,
+ "Total PRs": icons.prs,
+ "Total Issues": icons.issues,
+ "Total Repos": icons.contribs,
+ };
+
+ return iconMap[label] || icons.star; // Default to star if not found
+}
+
+/**
+ * Generates a stat item for the card with a playful card-style layout
+ * FIXED VERSION - Nested transforms properly
+ */
+export function generateStatItem(
+ label: string,
+ value: string | number,
+ index: number,
+ bold = true,
+): string {
+ // Arrange stats in a 2-column grid layout with playful rotations
+ const col = index % 2;
+ const row = Math.floor(index / 2);
+
+ const xOffset = 20 + col * 240;
+ const yOffset = 55 + row * 60;
+
+ // Playful rotations alternating between slight angles
+ const rotations = [-1.5, 1.2, 0.8, -1, 1.5];
+ const rotation = rotations[index % rotations.length];
+
+ const icon = getStatIcon(label);
+
+ return `
+
+
+
+
+
+
+
+
+
+ ${escapeXml(label)}
+
+
+ ${escapeXml(String(value))}
+
+
+ `;
+}
+
+/**
+ * Generates a language stat item with playful card styling
+ */
+export function generateLanguageItem(
+ name: string,
+ percent: number,
+ index: number,
+ color: string,
+ borderColor: string,
+): string {
+ const yOffset = 55 + index * 50;
+ const barWidth = (percent / 100) * 360;
+
+ return `
+
+
+
+
+
+
+ ${escapeXml(name)}
+ ${percent.toFixed(1)}%
+
+
+
+
+
+
+
+
+ `;
+}
+
+/**
+ * Escapes text for safe use in SVG
+ */
+export function escapeXml(text: string): string {
+ return text
+ .replace(/&/g, "&")
+ .replace(/ {
+ const headers: HeadersInit = {
+ Accept: "application/vnd.github+json",
+ };
+
+ if (token) {
+ headers["Authorization"] = `Bearer ${token}`;
+ }
+
+ try {
+ // Fetch user data
+ const userResponse = await fetch(
+ `https://api.github.com/users/${username}`,
+ { headers },
+ );
+ if (!userResponse.ok) {
+ throw new Error(`GitHub API error: ${userResponse.status}`);
+ }
+
+ // Fetch user repositories
+ const reposResponse = await fetch(
+ `https://api.github.com/users/${username}/repos?per_page=100&type=owner`,
+ { headers },
+ );
+
+ if (!reposResponse.ok) {
+ throw new Error(`GitHub API error: ${reposResponse.status}`);
+ }
+
+ const repos: GitHubRepo[] = await reposResponse.json();
+
+ // Calculate total stars
+ const totalStars = repos.reduce(
+ (acc, repo) => acc + repo.stargazers_count,
+ 0,
+ );
+
+ // Fetch commit count (this is an approximation using search API)
+ let totalCommits = 0;
+ const commitsResponse = await fetch(
+ `https://api.github.com/search/commits?q=author:${username}`,
+ { headers },
+ );
+ if (commitsResponse.ok) {
+ const commitsData =
+ (await commitsResponse.json()) as GitHubSearchResponse;
+ totalCommits = commitsData.total_count || 0;
+ }
+
+ // Fetch PRs
+ let totalPRs = 0;
+ const prsResponse = await fetch(
+ `https://api.github.com/search/issues?q=author:${username}+type:pr`,
+ { headers },
+ );
+ if (prsResponse.ok) {
+ const prsData = (await prsResponse.json()) as GitHubSearchResponse;
+ totalPRs = prsData.total_count || 0;
+ }
+
+ // Fetch Issues
+ let totalIssues = 0;
+ const issuesResponse = await fetch(
+ `https://api.github.com/search/issues?q=author:${username}+type:issue`,
+ { headers },
+ );
+ if (issuesResponse.ok) {
+ const issuesData = (await issuesResponse.json()) as GitHubSearchResponse;
+ totalIssues = issuesData.total_count || 0;
+ }
+
+ // Calculate rank based on total stars
+ let rank = "C";
+ if (totalStars >= 1000) {
+ rank = "S";
+ } else if (totalStars >= 500) {
+ rank = "A+";
+ } else if (totalStars >= 200) {
+ rank = "A";
+ } else if (totalStars >= 100) {
+ rank = "B+";
+ } else if (totalStars >= 50) {
+ rank = "B";
+ }
+
+ return {
+ username,
+ totalStars,
+ totalCommits,
+ totalPRs,
+ totalIssues,
+ contributedTo: repos.length, // This represents total owned repos, not repos contributed to
+ rank,
+ };
+ } catch (error) {
+ console.error("Error fetching GitHub stats:", error);
+ throw error;
+ }
+}
diff --git a/lib/languages.ts b/lib/languages.ts
new file mode 100644
index 0000000..2155bb7
--- /dev/null
+++ b/lib/languages.ts
@@ -0,0 +1,95 @@
+/**
+ * Language statistics utilities for GitHub users
+ */
+
+import { LanguageStats, LanguageData, GitHubRepoItem } from "./types.js";
+
+/**
+ * Fetches language statistics for a GitHub user
+ * @param username GitHub username
+ * @param token Optional GitHub token for higher rate limits
+ * @param exclude Comma-separated list of languages to exclude (e.g., "HTML,CSS")
+ */
+export async function fetchLanguageStats(
+ username: string,
+ token?: string,
+ exclude?: string,
+): Promise {
+ const headers: HeadersInit = {
+ Accept: "application/vnd.github+json",
+ };
+
+ if (token) {
+ headers["Authorization"] = `Bearer ${token}`;
+ }
+
+ try {
+ // Fetch user repositories
+ const reposResponse = await fetch(
+ `https://api.github.com/users/${username}/repos?per_page=100&type=owner`,
+ { headers },
+ );
+
+ if (!reposResponse.ok) {
+ throw new Error(`GitHub API error: ${reposResponse.status}`);
+ }
+
+ const repos = (await reposResponse.json()) as GitHubRepoItem[];
+
+ // Parse excluded languages
+ const excludedLanguages = exclude
+ ? exclude.split(",").map((lang) => lang.trim().toLowerCase())
+ : [];
+
+ // Aggregate language stats
+ const languageStats: LanguageStats = {};
+
+ for (const repo of repos) {
+ if (repo.fork) {
+ continue;
+ } // Skip forked repos
+
+ // Fetch languages for each repo
+ const langResponse = await fetch(repo.languages_url, { headers });
+
+ if (!langResponse.ok) {
+ console.warn(`Failed to fetch languages for repo ${repo.name}`);
+ continue;
+ }
+
+ const languages = (await langResponse.json()) as Record;
+
+ for (const [lang, bytes] of Object.entries(languages)) {
+ // Skip excluded languages
+ if (excludedLanguages.includes(lang.toLowerCase())) {
+ continue;
+ }
+ languageStats[lang] = (languageStats[lang] || 0) + bytes;
+ }
+ }
+
+ return languageStats;
+ } catch (error) {
+ console.error("Error fetching language stats:", error);
+ throw error;
+ }
+}
+
+/**
+ * Get top N languages by bytes
+ */
+export function getTopLanguages(
+ stats: LanguageStats,
+ limit = 5,
+): LanguageData[] {
+ const total = Object.values(stats).reduce((sum, bytes) => sum + bytes, 0);
+
+ return Object.entries(stats)
+ .map(([name, bytes]) => ({
+ name,
+ bytes,
+ percent: (bytes / total) * 100,
+ }))
+ .sort((a, b) => b.bytes - a.bytes)
+ .slice(0, limit);
+}
diff --git a/lib/themes.ts b/lib/themes.ts
new file mode 100644
index 0000000..49eb5c8
--- /dev/null
+++ b/lib/themes.ts
@@ -0,0 +1,67 @@
+/**
+ * Theme definitions for GitHub Flex badges
+ */
+
+import { Theme, ThemeName } from "./types.js";
+
+/**
+ * Available themes with color configurations
+ */
+export const themes: Record = {
+ [ThemeName.Default]: {
+ bg: "#fffef9",
+ title: "#ff6b6b",
+ text: "#5f6368",
+ icon: "#4ecdc4",
+ border: "#ff6b6b",
+ },
+ [ThemeName.Dark]: {
+ bg: "#1a1a2e",
+ title: "#f4d35e",
+ text: "#e8e8e8",
+ icon: "#95e1d3",
+ border: "#f4d35e",
+ },
+ [ThemeName.Radical]: {
+ bg: "#141321",
+ title: "#ff6bcb",
+ text: "#a9fef7",
+ icon: "#ffd93d",
+ border: "#ff6bcb",
+ },
+ [ThemeName.Merko]: {
+ bg: "#0f1c14",
+ title: "#c1ff72",
+ text: "#68b587",
+ icon: "#ffeb3b",
+ border: "#c1ff72",
+ },
+ [ThemeName.Gruvbox]: {
+ bg: "#282828",
+ title: "#fabd2f",
+ text: "#8ec07c",
+ icon: "#fe8019",
+ border: "#fabd2f",
+ },
+ [ThemeName.TokyoNight]: {
+ bg: "#1a1b27",
+ title: "#70a5fd",
+ text: "#38bdae",
+ icon: "#bf91f3",
+ border: "#70a5fd",
+ },
+ [ThemeName.Bubblegum]: {
+ bg: "#fff0f5",
+ title: "#ff1493",
+ text: "#8b4789",
+ icon: "#ff69b4",
+ border: "#ff69b4",
+ },
+ [ThemeName.Ocean]: {
+ bg: "#e0f7ff",
+ title: "#0077be",
+ text: "#2c5f7c",
+ icon: "#00d4ff",
+ border: "#00a8e8",
+ },
+};
diff --git a/lib/types.ts b/lib/types.ts
new file mode 100644
index 0000000..f4bf543
--- /dev/null
+++ b/lib/types.ts
@@ -0,0 +1,113 @@
+/**
+ * Theme names enum
+ */
+export enum ThemeName {
+ Default = "default",
+ Dark = "dark",
+ Radical = "radical",
+ Merko = "merko",
+ Gruvbox = "gruvbox",
+ TokyoNight = "tokyonight",
+ Bubblegum = "bubblegum",
+ Ocean = "ocean",
+}
+
+/**
+ * Theme color configuration
+ */
+export interface Theme {
+ bg: string;
+ title: string;
+ text: string;
+ icon: string;
+ border: string;
+}
+
+/**
+ * Card generation options
+ */
+export interface CardOptions {
+ title: string;
+ width?: number;
+ height?: number;
+ theme?: ThemeName;
+ borderRadius?: number;
+ hideBorder?: boolean;
+}
+
+/**
+ * GitHub user statistics
+ */
+export interface GitHubStats {
+ username: string;
+ totalStars: number;
+ totalCommits: number;
+ totalPRs: number;
+ totalIssues: number;
+ contributedTo: number;
+ rank: string;
+}
+
+/**
+ * GitHub repository data
+ */
+export interface GitHubRepo {
+ name: string;
+ stargazers_count: number;
+ forks_count: number;
+}
+
+/**
+ * Language statistics (language name -> bytes)
+ */
+export interface LanguageStats {
+ [language: string]: number;
+}
+
+/**
+ * Language data with percentage
+ */
+export interface LanguageData {
+ name: string;
+ percent: number;
+ bytes: number;
+}
+
+/**
+ * Internal GitHub API types
+ */
+export interface GitHubSearchResponse {
+ total_count: number;
+ incomplete_results: boolean;
+ items: unknown[];
+}
+
+export interface GitHubRepoItem {
+ name: string;
+ fork: boolean;
+ languages_url: string;
+}
+
+/**
+ * Repository data for display
+ */
+export interface RepoData {
+ name: string;
+ description: string;
+ stars: number;
+ forks: number;
+ language: string;
+ openIssues: number;
+}
+
+/**
+ * GitHub API repository response
+ */
+export interface GitHubRepoResponse {
+ name: string;
+ description: string | null;
+ stargazers_count: number;
+ forks_count: number;
+ language: string | null;
+ open_issues_count: number;
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..2bc87e4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,55 @@
+{
+ "name": "github-flex",
+ "version": "0.1.0",
+ "type": "module",
+ "description": "Flex your GitHub stats with customizable SVG badges for your profile. Because your GitHub profile deserves to look as good as your code...right?!",
+ "main": "index.js",
+ "scripts": {
+ "build": "tsc",
+ "type-check": "tsc --noEmit",
+ "format:check": "prettier --check .",
+ "format:write": "prettier --write .",
+ "lint:check": "eslint .",
+ "lint:fix": "eslint . --fix"
+ },
+ "keywords": [
+ "github",
+ "stats",
+ "badges",
+ "svg",
+ "visualization",
+ "vercel",
+ "serverless",
+ "node",
+ "typescript",
+ "api",
+ "customizable",
+ "themes",
+ "languages",
+ "repositories",
+ "open-source"
+ ],
+ "author": "Alexandru Moraru",
+ "homepage": "https://github.com/alemoraru/github-flex",
+ "bugs": {
+ "url": "https://github.com/alemoraru/github-flex/issues"
+ },
+ "license": "MIT",
+ "dependencies": {
+ "@vercel/node": "^5.6.3"
+ },
+ "devDependencies": {
+ "@eslint/js": "^10.0.0",
+ "@types/node": "^25.2.3",
+ "@typescript-eslint/eslint-plugin": "^8.55.0",
+ "@typescript-eslint/parser": "^8.55.0",
+ "eslint": "^10.0.0",
+ "globals": "^17.3.0",
+ "prettier": "3.8.0",
+ "typescript": "^5.9.3",
+ "vercel": "^50.17.1"
+ },
+ "engines": {
+ "node": ">=23"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..a39a168
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,2770 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@vercel/node':
+ specifier: ^5.6.3
+ version: 5.6.3
+ devDependencies:
+ '@eslint/js':
+ specifier: ^10.0.0
+ version: 10.0.1(eslint@10.0.0)
+ '@types/node':
+ specifier: ^25.2.3
+ version: 25.2.3
+ '@typescript-eslint/eslint-plugin':
+ specifier: ^8.55.0
+ version: 8.55.0(@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.9.3))(eslint@10.0.0)(typescript@5.9.3)
+ '@typescript-eslint/parser':
+ specifier: ^8.55.0
+ version: 8.55.0(eslint@10.0.0)(typescript@5.9.3)
+ eslint:
+ specifier: ^10.0.0
+ version: 10.0.0
+ globals:
+ specifier: ^17.3.0
+ version: 17.3.0
+ prettier:
+ specifier: 3.8.0
+ version: 3.8.0
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+ vercel:
+ specifier: ^50.17.1
+ version: 50.17.1(@vercel/node@5.6.3)
+
+packages:
+
+ '@bytecodealliance/preview2-shim@0.17.6':
+ resolution: {integrity: sha512-n3cM88gTen5980UOBAD6xDcNNL3ocTK8keab21bpx1ONdA+ARj7uD1qoFxOWCyKlkpSi195FH+GeAut7Oc6zZw==}
+
+ '@edge-runtime/format@2.2.1':
+ resolution: {integrity: sha512-JQTRVuiusQLNNLe2W9tnzBlV/GvSVcozLl4XZHk5swnRZ/v6jp8TqR8P7sqmJsQqblDZ3EztcWmLDbhRje/+8g==}
+ engines: {node: '>=16'}
+
+ '@edge-runtime/node-utils@2.3.0':
+ resolution: {integrity: sha512-uUtx8BFoO1hNxtHjp3eqVPC/mWImGb2exOfGjMLUoipuWgjej+f4o/VP4bUI8U40gu7Teogd5VTeZUkGvJSPOQ==}
+ engines: {node: '>=16'}
+
+ '@edge-runtime/ponyfill@2.4.2':
+ resolution: {integrity: sha512-oN17GjFr69chu6sDLvXxdhg0Qe8EZviGSuqzR9qOiKh4MhFYGdBBcqRNzdmYeAdeRzOW2mM9yil4RftUQ7sUOA==}
+ engines: {node: '>=16'}
+
+ '@edge-runtime/primitives@4.1.0':
+ resolution: {integrity: sha512-Vw0lbJ2lvRUqc7/soqygUX216Xb8T3WBZ987oywz6aJqRxcwSVWwr9e+Nqo2m9bxobA9mdbWNNoRY6S9eko1EQ==}
+ engines: {node: '>=16'}
+
+ '@edge-runtime/vm@3.2.0':
+ resolution: {integrity: sha512-0dEVyRLM/lG4gp1R/Ik5bfPl/1wX00xFwd5KcNH602tzBa09oF7pbTKETEhR1GjZ75K6OJnYFu8II2dyMhONMw==}
+ engines: {node: '>=16'}
+
+ '@esbuild/aix-ppc64@0.27.0':
+ resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.27.0':
+ resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.27.0':
+ resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.27.0':
+ resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.27.0':
+ resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.27.0':
+ resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.27.0':
+ resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.27.0':
+ resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.27.0':
+ resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.27.0':
+ resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.27.0':
+ resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.27.0':
+ resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.27.0':
+ resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.27.0':
+ resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.27.0':
+ resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.27.0':
+ resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.27.0':
+ resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.27.0':
+ resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.27.0':
+ resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.27.0':
+ resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.27.0':
+ resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.27.0':
+ resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.27.0':
+ resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.27.0':
+ resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.27.0':
+ resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.27.0':
+ resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==}
+ 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}
+ 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/config-array@0.23.1':
+ resolution: {integrity: sha512-uVSdg/V4dfQmTjJzR0szNczjOH/J+FyUMMjYtr07xFRXR7EDf9i1qdxrD0VusZH9knj1/ecxzCQQxyic5NzAiA==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+ '@eslint/config-helpers@0.5.2':
+ resolution: {integrity: sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+ '@eslint/core@1.1.0':
+ resolution: {integrity: sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==}
+ 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.1':
+ resolution: {integrity: sha512-P9cq2dpr+LU8j3qbLygLcSZrl2/ds/pUpfnHNNuk5HW7mnngHs+6WSq5C9mO3rqRX8A1poxqLTC9cu0KOyJlBg==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+ '@eslint/plugin-kit@0.6.0':
+ resolution: {integrity: sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+ '@fastify/busboy@2.1.1':
+ resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
+ engines: {node: '>=14'}
+
+ '@humanfs/core@0.19.1':
+ resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanfs/node@0.16.7':
+ resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
+ engines: {node: '>=18.18.0'}
+
+ '@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'}
+
+ '@isaacs/balanced-match@4.0.1':
+ resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/brace-expansion@5.0.1':
+ resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==}
+ engines: {node: 20 || >=22}
+
+ '@isaacs/cliui@9.0.0':
+ resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==}
+ engines: {node: '>=18'}
+
+ '@isaacs/fs-minipass@4.0.1':
+ resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+ engines: {node: '>=18.0.0'}
+
+ '@mapbox/node-pre-gyp@2.0.3':
+ resolution: {integrity: sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@renovatebot/pep440@4.2.1':
+ resolution: {integrity: sha512-2FK1hF93Fuf1laSdfiEmJvSJPVIDHEUTz68D3Fi9s0IZrrpaEcj6pTFBTbYvsgC5du4ogrtf5re7yMMvrKNgkw==}
+ engines: {node: ^20.9.0 || ^22.11.0 || ^24, pnpm: ^10.0.0}
+
+ '@rollup/pluginutils@5.3.0':
+ resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
+ '@tootallnate/once@2.0.0':
+ resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
+ engines: {node: '>= 10'}
+
+ '@tootallnate/quickjs-emscripten@0.23.0':
+ resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
+
+ '@ts-morph/common@0.11.1':
+ resolution: {integrity: sha512-7hWZS0NRpEsNV8vWJzg7FEz6V8MaLNeJOmwmghqUXTpzk16V1LLZhdo+4QvE/+zv4cVci0OviuJFnqhEfoV3+g==}
+
+ '@types/esrecurse@4.3.1':
+ resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+ '@types/node@20.11.0':
+ resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==}
+
+ '@types/node@25.2.3':
+ resolution: {integrity: sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==}
+
+ '@typescript-eslint/eslint-plugin@8.55.0':
+ resolution: {integrity: sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.55.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/parser@8.55.0':
+ resolution: {integrity: sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/project-service@8.55.0':
+ resolution: {integrity: sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/scope-manager@8.55.0':
+ resolution: {integrity: sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/tsconfig-utils@8.55.0':
+ resolution: {integrity: sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/type-utils@8.55.0':
+ resolution: {integrity: sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/types@8.55.0':
+ resolution: {integrity: sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/typescript-estree@8.55.0':
+ resolution: {integrity: sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/utils@8.55.0':
+ resolution: {integrity: sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/visitor-keys@8.55.0':
+ resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@vercel/blob@1.0.2':
+ resolution: {integrity: sha512-Im/KeFH4oPx7UsM+QiteimnE07bIUD7JK6CBafI9Z0jRFogaialTBMiZj8EKk/30ctUYsrpIIyP9iIY1YxWnUQ==}
+ engines: {node: '>=16.14'}
+
+ '@vercel/build-utils@13.4.0':
+ resolution: {integrity: sha512-hGBYt+olxUtDZu0W8DKl4NjY8tQC1eJUxDpkJdOhcugap4NnHeHZQ33vEKs0Z72bYlqotgu0AoEOv+ri5rlh4w==}
+
+ '@vercel/detect-agent@1.1.0':
+ resolution: {integrity: sha512-Zfq6FbIcYl9gaAmVu6ROsqUiCNwpEj3Ljz/tMX5fl12Z95OFOxzf7vlO03WE5JBU/ri1tBDFHnW41dihMINOPQ==}
+ engines: {node: '>=14'}
+
+ '@vercel/error-utils@2.0.3':
+ resolution: {integrity: sha512-CqC01WZxbLUxoiVdh9B/poPbNpY9U+tO1N9oWHwTl5YAZxcqXmmWJ8KNMFItJCUUWdY3J3xv8LvAuQv2KZ5YdQ==}
+
+ '@vercel/fun@1.3.0':
+ resolution: {integrity: sha512-8erw9uPe0dFg45THkNxmjtvMX143SkZebmjgSVbcM3XCkXu3RIiBaJMcMNG8aaS+rnTuw8+d4De9HVT0M/r3wg==}
+ engines: {node: '>= 18'}
+
+ '@vercel/nft@1.1.1':
+ resolution: {integrity: sha512-mKMGa7CEUcXU75474kOeqHbtvK1kAcu4wiahhmlUenB5JbTQB8wVlDI8CyHR3rpGo0qlzoRWqcDzI41FUoBJCA==}
+ engines: {node: '>=20'}
+ hasBin: true
+
+ '@vercel/node@5.6.3':
+ resolution: {integrity: sha512-sordxYoSnYquTxQ2sSIubukhZtAThSAjT+A+ACFac9nkOWyPfW83eQINPWBD/xotdNm3w+1v/afkt427GbXfNg==}
+
+ '@vercel/python-analysis@0.4.1':
+ resolution: {integrity: sha512-Ae6zayRNAO//z9ULOV+T8sjJFJLfA0OU540/BDkaVWHWhlqElIA7uyi71WuD7Ls06CDVpKYNRysv3keJaVbwow==}
+
+ '@vercel/static-config@3.1.2':
+ resolution: {integrity: sha512-2d+TXr6K30w86a+WbMbGm2W91O0UzO5VeemZYBBUJbCjk/5FLLGIi8aV6RS2+WmaRvtcqNTn2pUA7nCOK3bGcQ==}
+
+ abbrev@3.0.1:
+ resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==}
+ engines: {node: ^18.17.0 || >=20.5.0}
+
+ acorn-import-attributes@1.9.5:
+ resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==}
+ peerDependencies:
+ acorn: ^8
+
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+ ajv@8.6.3:
+ resolution: {integrity: sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==}
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ arg@4.1.0:
+ resolution: {integrity: sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ ast-types@0.13.4:
+ resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
+ engines: {node: '>=4'}
+
+ async-listen@1.2.0:
+ resolution: {integrity: sha512-CcEtRh/oc9Jc4uWeUwdpG/+Mb2YUHKmdaTf0gUr7Wa+bfp4xx70HOb3RuSTJMvqKNB1TkdTfjLdrcz2X4rkkZA==}
+
+ async-listen@3.0.0:
+ resolution: {integrity: sha512-V+SsTpDqkrWTimiotsyl33ePSjA5/KrithwupuvJ6ztsqPvGv6ge4OredFhPffVXiLN/QUWvE0XcqJaYgt6fOg==}
+ engines: {node: '>= 14'}
+
+ async-listen@3.0.1:
+ resolution: {integrity: sha512-cWMaNwUJnf37C/S5TfCkk/15MwbPRwVYALA2jtjkbHjCmAPiDXyNJy2q3p1KAZzDLHAWyarUWSujUoHR4pEgrA==}
+ engines: {node: '>= 14'}
+
+ async-retry@1.3.3:
+ resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==}
+
+ async-sema@3.1.1:
+ resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ balanced-match@4.0.2:
+ resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==}
+ engines: {node: 20 || >=22}
+
+ basic-ftp@5.1.0:
+ resolution: {integrity: sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==}
+ engines: {node: '>=10.0.0'}
+
+ bindings@1.5.0:
+ resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
+
+ brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
+
+ brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+
+ brace-expansion@5.0.2:
+ resolution: {integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==}
+ engines: {node: 20 || >=22}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+
+ bytes@3.1.0:
+ resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==}
+ engines: {node: '>= 0.8'}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ chokidar@4.0.0:
+ resolution: {integrity: sha512-mxIojEAQcuEvT/lyXq+jf/3cO/KoA6z4CeNDGGevTybECPOMFCnQy3OPahluUkbqgPNGw5Bi78UC7Po6Lhy+NA==}
+ engines: {node: '>= 14.16.0'}
+
+ chownr@3.0.0:
+ resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+ engines: {node: '>=18'}
+
+ cjs-module-lexer@1.2.3:
+ resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==}
+
+ code-block-writer@10.1.1:
+ resolution: {integrity: sha512-67ueh2IRGst/51p0n6FvPrnRjAGHY5F8xdjkgrYE7DDzpJe6qA07RYQ9VcoUeo5ATOjSOiWpSL3SWBRRbempMw==}
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ consola@3.4.2:
+ resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
+ engines: {node: ^14.18.0 || >=16.10.0}
+
+ content-type@1.0.4:
+ resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==}
+ engines: {node: '>= 0.6'}
+
+ convert-hrtime@3.0.0:
+ resolution: {integrity: sha512-7V+KqSvMiHp8yWDuwfww06XleMWVVB9b9tURBx+G7UTADuo5hYPuowKloz4OzOqbPezxgo+fdQ1522WzPG4OeA==}
+ engines: {node: '>=8'}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ data-uri-to-buffer@6.0.2:
+ resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
+ engines: {node: '>= 14'}
+
+ debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+ degenerator@5.0.1:
+ resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
+ engines: {node: '>= 14'}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ depd@1.1.2:
+ resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
+ engines: {node: '>= 0.6'}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ edge-runtime@2.5.9:
+ resolution: {integrity: sha512-pk+k0oK0PVXdlT4oRp4lwh+unuKB7Ng4iZ2HB+EZ7QCEQizX360Rp/F4aRpgpRgdP2ufB35N+1KppHmYjqIGSg==}
+ engines: {node: '>=16'}
+ hasBin: true
+
+ end-of-stream@1.1.0:
+ resolution: {integrity: sha512-EoulkdKF/1xa92q25PbjuDcgJ9RDHYU2Rs3SCIvs2/dSQ3BpmxneNHmA/M7fe60M3PrV7nNGTTNbkK62l6vXiQ==}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-module-lexer@1.4.1:
+ resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+
+ esbuild@0.27.0:
+ resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ escodegen@2.1.0:
+ resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==}
+ engines: {node: '>=6.0'}
+ hasBin: true
+
+ eslint-scope@9.1.0:
+ resolution: {integrity: sha512-CkWE42hOJsNj9FJRaoMX9waUFYhqY4jmyLFdAdzZr6VaCg3ynLYx4WnOdkaIifGfH4gsUcBTn4OZbHXkpLD0FQ==}
+ 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}
+
+ eslint-visitor-keys@4.2.1:
+ resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint-visitor-keys@5.0.0:
+ resolution: {integrity: sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+ eslint@10.0.0:
+ resolution: {integrity: sha512-O0piBKY36YSJhlFSG8p9VUdPV/SxxS4FYDWVpr/9GJuMaepzwlf4J8I4ov1b+ySQfDTPhc3DtLaxcT1fN0yqCg==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+ hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+
+ espree@11.1.0:
+ resolution: {integrity: sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==}
+ engines: {node: ^20.19.0 || ^22.13.0 || >=24}
+
+ esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ esquery@1.7.0:
+ 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'}
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+ esutils@2.0.3:
+ 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'}
+
+ events-intercept@2.0.0:
+ resolution: {integrity: sha512-blk1va0zol9QOrdZt0rFXo5KMkNPVSp92Eju/Qz8THwKWKRKeE0T8Br/1aW6+Edkyq9xHYgYxn2QtOnUKPUp+Q==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+ fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+ fd-slicer@1.1.0:
+ resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ file-entry-cache@8.0.0:
+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+ engines: {node: '>=16.0.0'}
+
+ file-uri-to-path@1.0.0:
+ resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
+ flat-cache@4.0.1:
+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+ engines: {node: '>=16'}
+
+ flatted@3.3.3:
+ resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
+
+ form-data@4.0.5:
+ resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
+ engines: {node: '>= 6'}
+
+ fs-extra@11.1.1:
+ resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==}
+ engines: {node: '>=14.14'}
+
+ fsevents@2.3.3:
+ 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==}
+
+ generic-pool@3.4.2:
+ resolution: {integrity: sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==}
+ engines: {node: '>= 4'}
+
+ get-intrinsic@1.3.0:
+ 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'}
+
+ get-tsconfig@4.13.6:
+ resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==}
+
+ get-uri@6.0.5:
+ resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==}
+ engines: {node: '>= 14'}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+
+ glob@13.0.3:
+ resolution: {integrity: sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==}
+ engines: {node: 20 || >=22}
+
+ globals@17.3.0:
+ resolution: {integrity: sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==}
+ engines: {node: '>=18'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ http-errors@1.7.3:
+ resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==}
+ engines: {node: '>= 0.6'}
+
+ http-proxy-agent@7.0.2:
+ resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
+ engines: {node: '>= 14'}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ iconv-lite@0.4.24:
+ resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
+ engines: {node: '>=0.10.0'}
+
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ ignore@7.0.5:
+ resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
+ engines: {node: '>= 4'}
+
+ imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ip-address@10.1.0:
+ resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==}
+ engines: {node: '>= 12'}
+
+ is-buffer@2.0.5:
+ resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
+ engines: {node: '>=4'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-node-process@1.2.0:
+ resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jackspeak@4.2.3:
+ resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==}
+ engines: {node: 20 || >=22}
+
+ jose@5.9.6:
+ resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
+
+ js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-schema-to-ts@1.6.4:
+ resolution: {integrity: sha512-pR4yQ9DHz6itqswtHCm26mw45FSNfQ9rEQjosaZErhn5J3J2sIViQiz8rDaezjKAhFGpmsoczYVBgGHzFw/stA==}
+
+ json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+ json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+
+ json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+ jsonfile@6.2.0:
+ resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==}
+
+ keyv@4.5.4:
+ 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'}
+
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
+ lru-cache@11.2.6:
+ resolution: {integrity: sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==}
+ engines: {node: 20 || >=22}
+
+ lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+
+ lru-cache@7.18.3:
+ resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
+ engines: {node: '>=12'}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micro@9.3.5-canary.3:
+ resolution: {integrity: sha512-viYIo9PefV+w9dvoIBh1gI44Mvx1BOk67B4BpC2QK77qdY0xZF0Q+vWLt/BII6cLkIc8rLmSIcJaB/OrXXKe1g==}
+ engines: {node: '>= 8.0.0'}
+ hasBin: true
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ minimatch@10.1.1:
+ resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
+ engines: {node: 20 || >=22}
+
+ minimatch@10.2.0:
+ resolution: {integrity: sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==}
+ engines: {node: 20 || >=22}
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minizlib@3.1.0:
+ resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
+ engines: {node: '>= 18'}
+
+ mkdirp@1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+
+ ms@2.1.1:
+ resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==}
+
+ ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+ netmask@2.0.2:
+ resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
+ engines: {node: '>= 0.4.0'}
+
+ node-fetch@2.6.7:
+ resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
+ node-fetch@2.6.9:
+ resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
+ node-gyp-build@4.8.4:
+ resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==}
+ hasBin: true
+
+ nopt@8.1.0:
+ resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==}
+ engines: {node: ^18.17.0 || >=20.5.0}
+ hasBin: true
+
+ ohm-js@17.5.0:
+ resolution: {integrity: sha512-l4Sa7026+6jsvYbt0PXKmL+f+ML32fD++IznLgxDhx2t9Cx6NC7zwRqblCujPHGGmkQerHoeBzRutdxaw/S72g==}
+ engines: {node: '>=0.12.1'}
+
+ once@1.3.3:
+ resolution: {integrity: sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==}
+
+ optionator@0.9.4:
+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+ engines: {node: '>= 0.8.0'}
+
+ os-paths@4.4.0:
+ resolution: {integrity: sha512-wrAwOeXp1RRMFfQY8Sy7VaGVmPocaLwSFOYCGKSyo8qmJ+/yaafCl5BCA1IQZWqFSRBrKDYFeR9d/VyQzfH/jg==}
+ engines: {node: '>= 6.0'}
+
+ p-limit@3.1.0:
+ 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'}
+
+ pac-proxy-agent@7.2.0:
+ resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==}
+ engines: {node: '>= 14'}
+
+ pac-resolver@7.0.1:
+ resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==}
+ engines: {node: '>= 14'}
+
+ parse-ms@2.1.0:
+ resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==}
+ engines: {node: '>=6'}
+
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-scurry@2.0.1:
+ resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
+ engines: {node: 20 || >=22}
+
+ path-to-regexp@6.1.0:
+ resolution: {integrity: sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==}
+
+ path-to-regexp@6.3.0:
+ resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
+
+ path-to-regexp@8.2.0:
+ resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
+ engines: {node: '>=16'}
+
+ pend@1.2.0:
+ resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+
+ picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pip-requirements-js@1.0.2:
+ resolution: {integrity: sha512-awqoNOSOl4Blu4E4Hzp7jL0g8WKEhCwO+s7C2ibtIW3CAJMwspgoTXd4vnHd21UmhdrsI44Pn8FFSuA8QKrzvg==}
+
+ prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+
+ prettier@3.8.0:
+ resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==}
+ engines: {node: '>=14'}
+ hasBin: true
+
+ pretty-ms@7.0.1:
+ resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==}
+ engines: {node: '>=10'}
+
+ promisepipe@3.0.0:
+ resolution: {integrity: sha512-V6TbZDJ/ZswevgkDNpGt/YqNCiZP9ASfgU+p83uJE6NrGtvSGoOcHLiDCqkMs2+yg7F5qHdLV8d0aS8O26G/KA==}
+
+ proxy-agent@6.4.0:
+ resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==}
+ engines: {node: '>= 14'}
+
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ raw-body@2.4.1:
+ resolution: {integrity: sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==}
+ engines: {node: '>= 0.8'}
+
+ readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
+
+ require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+
+ resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
+ retry@0.13.1:
+ resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
+ engines: {node: '>= 4'}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ semver@7.5.4:
+ resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ semver@7.7.4:
+ resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ setprototypeof@1.1.1:
+ resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ signal-exit@4.0.2:
+ resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==}
+ engines: {node: '>=14'}
+
+ smart-buffer@4.2.0:
+ resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
+ engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
+
+ smol-toml@1.5.2:
+ resolution: {integrity: sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==}
+ engines: {node: '>= 18'}
+
+ socks-proxy-agent@8.0.5:
+ resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==}
+ engines: {node: '>= 14'}
+
+ socks@2.8.7:
+ resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==}
+ engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
+ stat-mode@0.3.0:
+ resolution: {integrity: sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==}
+
+ statuses@1.5.0:
+ resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==}
+ engines: {node: '>= 0.6'}
+
+ stream-to-array@2.3.0:
+ resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==}
+
+ stream-to-promise@2.2.0:
+ resolution: {integrity: sha512-HAGUASw8NT0k8JvIVutB2Y/9iBk7gpgEyAudXwNJmZERdMITGdajOa4VJfD/kNiA3TppQpTP4J+CtcHwdzKBAw==}
+
+ tar@7.5.7:
+ resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==}
+ engines: {node: '>=18'}
+
+ throttleit@2.1.0:
+ resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==}
+ engines: {node: '>=18'}
+
+ time-span@4.0.0:
+ resolution: {integrity: sha512-MyqZCTGLDZ77u4k+jqg4UlrzPTPZ49NDlaekU6uuFaJLzPIN1woaRXCbGeqOfxwc3Y37ZROGAJ614Rdv7Olt+g==}
+ engines: {node: '>=10'}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ toidentifier@1.0.0:
+ resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==}
+ engines: {node: '>=0.6'}
+
+ tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
+ tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+
+ ts-api-utils@2.4.0:
+ resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
+ engines: {node: '>=18.12'}
+ peerDependencies:
+ typescript: '>=4.8.4'
+
+ ts-morph@12.0.0:
+ resolution: {integrity: sha512-VHC8XgU2fFW7yO1f/b3mxKDje1vmyzFXHWzOYmKEkCEwcLjDtbdLgBQviqj4ZwP4MJkQtRo6Ha2I29lq/B+VxA==}
+
+ ts-toolbelt@6.15.5:
+ resolution: {integrity: sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ tsx@4.21.0:
+ resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==}
+ engines: {node: '>=18.0.0'}
+ hasBin: true
+
+ type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ uid-promise@1.0.0:
+ resolution: {integrity: sha512-R8375j0qwXyIu/7R0tjdF06/sElHqbmdmWC9M2qQHpEVbvE4I5+38KJI7LUUmQMp7NVq4tKHiBMkT0NFM453Ig==}
+
+ undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+
+ undici-types@7.16.0:
+ resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
+
+ undici@5.28.4:
+ resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==}
+ engines: {node: '>=14.0'}
+
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+ vercel@50.17.1:
+ resolution: {integrity: sha512-ffbavqxjpiLco2Yh7sAnU5npKli663wVyD/bMeJPRZCBGexzZUZo/GGn1hHQzoIh3hKNV0rIXsXUan7PD4HYKg==}
+ engines: {node: '>= 18'}
+ hasBin: true
+ peerDependencies:
+ '@vercel/backends': 0.0.33
+ '@vercel/elysia': 0.1.36
+ '@vercel/express': 0.1.45
+ '@vercel/fastify': 0.1.39
+ '@vercel/go': 3.4.0
+ '@vercel/h3': 0.1.45
+ '@vercel/hono': 0.2.39
+ '@vercel/hydrogen': 1.3.5
+ '@vercel/koa': 0.1.19
+ '@vercel/nestjs': 0.2.40
+ '@vercel/next': 4.15.28
+ '@vercel/node': 5.6.3
+ '@vercel/python': 6.12.0
+ '@vercel/redwood': 2.4.9
+ '@vercel/remix-builder': 5.5.10
+ '@vercel/ruby': 2.3.0
+ '@vercel/rust': 1.0.5
+ '@vercel/static-build': 2.8.37
+ peerDependenciesMeta:
+ '@vercel/backends':
+ optional: true
+ '@vercel/elysia':
+ optional: true
+ '@vercel/express':
+ optional: true
+ '@vercel/fastify':
+ optional: true
+ '@vercel/go':
+ optional: true
+ '@vercel/h3':
+ optional: true
+ '@vercel/hono':
+ optional: true
+ '@vercel/hydrogen':
+ optional: true
+ '@vercel/koa':
+ optional: true
+ '@vercel/nestjs':
+ optional: true
+ '@vercel/next':
+ optional: true
+ '@vercel/node':
+ optional: true
+ '@vercel/python':
+ optional: true
+ '@vercel/redwood':
+ optional: true
+ '@vercel/remix-builder':
+ optional: true
+ '@vercel/ruby':
+ optional: true
+ '@vercel/rust':
+ optional: true
+ '@vercel/static-build':
+ optional: true
+
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ word-wrap@1.2.5:
+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+ engines: {node: '>=0.10.0'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ xdg-app-paths@5.1.0:
+ resolution: {integrity: sha512-RAQ3WkPf4KTU1A8RtFx3gWywzVKe00tfOPFfl2NDGqbIFENQO4kqAJp7mhQjNj/33W5x5hiWWUdyfPq/5SU3QA==}
+ engines: {node: '>=6'}
+
+ xdg-portable@7.3.0:
+ resolution: {integrity: sha512-sqMMuL1rc0FmMBOzCpd0yuy9trqF2yTTVe+E9ogwCSWQCdDEtQUwrZPT6AxqtsFGRNxycgncbP/xmOOSPw5ZUw==}
+ engines: {node: '>= 6.0'}
+
+ yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+
+ yallist@5.0.0:
+ resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+ engines: {node: '>=18'}
+
+ yauzl-clone@1.0.4:
+ resolution: {integrity: sha512-igM2RRCf3k8TvZoxR2oguuw4z1xasOnA31joCqHIyLkeWrvAc2Jgay5ISQ2ZplinkoGaJ6orCz56Ey456c5ESA==}
+ engines: {node: '>=6'}
+
+ yauzl-promise@2.1.3:
+ resolution: {integrity: sha512-A1pf6fzh6eYkK0L4Qp7g9jzJSDrM6nN0bOn5T0IbY4Yo3w+YkWlHFkJP7mzknMXjqusHFHlKsK2N+4OLsK2MRA==}
+ engines: {node: '>=6'}
+
+ yauzl@2.10.0:
+ resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
+
+ yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+
+ zod@3.22.4:
+ resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
+
+snapshots:
+
+ '@bytecodealliance/preview2-shim@0.17.6': {}
+
+ '@edge-runtime/format@2.2.1': {}
+
+ '@edge-runtime/node-utils@2.3.0': {}
+
+ '@edge-runtime/ponyfill@2.4.2': {}
+
+ '@edge-runtime/primitives@4.1.0': {}
+
+ '@edge-runtime/vm@3.2.0':
+ dependencies:
+ '@edge-runtime/primitives': 4.1.0
+
+ '@esbuild/aix-ppc64@0.27.0':
+ optional: true
+
+ '@esbuild/android-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/android-arm@0.27.0':
+ optional: true
+
+ '@esbuild/android-x64@0.27.0':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/darwin-x64@0.27.0':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.27.0':
+ optional: true
+
+ '@esbuild/linux-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/linux-arm@0.27.0':
+ optional: true
+
+ '@esbuild/linux-ia32@0.27.0':
+ optional: true
+
+ '@esbuild/linux-loong64@0.27.0':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.27.0':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.27.0':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.27.0':
+ optional: true
+
+ '@esbuild/linux-s390x@0.27.0':
+ optional: true
+
+ '@esbuild/linux-x64@0.27.0':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.27.0':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.27.0':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/sunos-x64@0.27.0':
+ optional: true
+
+ '@esbuild/win32-arm64@0.27.0':
+ optional: true
+
+ '@esbuild/win32-ia32@0.27.0':
+ optional: true
+
+ '@esbuild/win32-x64@0.27.0':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.9.1(eslint@10.0.0)':
+ dependencies:
+ eslint: 10.0.0
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.12.2': {}
+
+ '@eslint/config-array@0.23.1':
+ dependencies:
+ '@eslint/object-schema': 3.0.1
+ debug: 4.4.3
+ minimatch: 10.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/config-helpers@0.5.2':
+ dependencies:
+ '@eslint/core': 1.1.0
+
+ '@eslint/core@1.1.0':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
+ '@eslint/js@10.0.1(eslint@10.0.0)':
+ optionalDependencies:
+ eslint: 10.0.0
+
+ '@eslint/object-schema@3.0.1': {}
+
+ '@eslint/plugin-kit@0.6.0':
+ dependencies:
+ '@eslint/core': 1.1.0
+ levn: 0.4.1
+
+ '@fastify/busboy@2.1.1': {}
+
+ '@humanfs/core@0.19.1': {}
+
+ '@humanfs/node@0.16.7':
+ dependencies:
+ '@humanfs/core': 0.19.1
+ '@humanwhocodes/retry': 0.4.3
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/retry@0.4.3': {}
+
+ '@isaacs/balanced-match@4.0.1': {}
+
+ '@isaacs/brace-expansion@5.0.1':
+ dependencies:
+ '@isaacs/balanced-match': 4.0.1
+
+ '@isaacs/cliui@9.0.0': {}
+
+ '@isaacs/fs-minipass@4.0.1':
+ dependencies:
+ minipass: 7.1.2
+
+ '@mapbox/node-pre-gyp@2.0.3':
+ dependencies:
+ consola: 3.4.2
+ detect-libc: 2.1.2
+ https-proxy-agent: 7.0.6
+ node-fetch: 2.6.9
+ nopt: 8.1.0
+ semver: 7.7.4
+ tar: 7.5.7
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.1
+
+ '@renovatebot/pep440@4.2.1': {}
+
+ '@rollup/pluginutils@5.3.0':
+ dependencies:
+ '@types/estree': 1.0.8
+ estree-walker: 2.0.2
+ picomatch: 4.0.3
+
+ '@tootallnate/once@2.0.0': {}
+
+ '@tootallnate/quickjs-emscripten@0.23.0': {}
+
+ '@ts-morph/common@0.11.1':
+ dependencies:
+ fast-glob: 3.3.3
+ minimatch: 3.1.2
+ mkdirp: 1.0.4
+ path-browserify: 1.0.1
+
+ '@types/esrecurse@4.3.1': {}
+
+ '@types/estree@1.0.8': {}
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/node@20.11.0':
+ dependencies:
+ undici-types: 5.26.5
+
+ '@types/node@25.2.3':
+ dependencies:
+ undici-types: 7.16.0
+
+ '@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.9.3))(eslint@10.0.0)(typescript@5.9.3)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.2
+ '@typescript-eslint/parser': 8.55.0(eslint@10.0.0)(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.55.0
+ '@typescript-eslint/type-utils': 8.55.0(eslint@10.0.0)(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.55.0(eslint@10.0.0)(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.55.0
+ eslint: 10.0.0
+ ignore: 7.0.5
+ natural-compare: 1.4.0
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@8.55.0(eslint@10.0.0)(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.55.0
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.55.0
+ debug: 4.4.3
+ eslint: 10.0.0
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/project-service@8.55.0(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.55.0
+ debug: 4.4.3
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@8.55.0':
+ dependencies:
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/visitor-keys': 8.55.0
+
+ '@typescript-eslint/tsconfig-utils@8.55.0(typescript@5.9.3)':
+ dependencies:
+ typescript: 5.9.3
+
+ '@typescript-eslint/type-utils@8.55.0(eslint@10.0.0)(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.55.0(eslint@10.0.0)(typescript@5.9.3)
+ debug: 4.4.3
+ eslint: 10.0.0
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@8.55.0': {}
+
+ '@typescript-eslint/typescript-estree@8.55.0(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/visitor-keys': 8.55.0
+ debug: 4.4.3
+ minimatch: 9.0.5
+ semver: 7.7.4
+ tinyglobby: 0.2.15
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.55.0(eslint@10.0.0)(typescript@5.9.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0)
+ '@typescript-eslint/scope-manager': 8.55.0
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3)
+ eslint: 10.0.0
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/visitor-keys@8.55.0':
+ dependencies:
+ '@typescript-eslint/types': 8.55.0
+ eslint-visitor-keys: 4.2.1
+
+ '@vercel/blob@1.0.2':
+ dependencies:
+ async-retry: 1.3.3
+ is-buffer: 2.0.5
+ is-node-process: 1.2.0
+ throttleit: 2.1.0
+ undici: 5.28.4
+
+ '@vercel/build-utils@13.4.0':
+ dependencies:
+ '@vercel/python-analysis': 0.4.1
+
+ '@vercel/detect-agent@1.1.0': {}
+
+ '@vercel/error-utils@2.0.3': {}
+
+ '@vercel/fun@1.3.0':
+ dependencies:
+ '@tootallnate/once': 2.0.0
+ async-listen: 1.2.0
+ debug: 4.3.4
+ generic-pool: 3.4.2
+ micro: 9.3.5-canary.3
+ ms: 2.1.1
+ node-fetch: 2.6.7
+ path-to-regexp: 8.2.0
+ promisepipe: 3.0.0
+ semver: 7.5.4
+ stat-mode: 0.3.0
+ stream-to-promise: 2.2.0
+ tar: 7.5.7
+ tinyexec: 0.3.2
+ tree-kill: 1.2.2
+ uid-promise: 1.0.0
+ xdg-app-paths: 5.1.0
+ yauzl-promise: 2.1.3
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ '@vercel/nft@1.1.1':
+ dependencies:
+ '@mapbox/node-pre-gyp': 2.0.3
+ '@rollup/pluginutils': 5.3.0
+ acorn: 8.15.0
+ acorn-import-attributes: 1.9.5(acorn@8.15.0)
+ async-sema: 3.1.1
+ bindings: 1.5.0
+ estree-walker: 2.0.2
+ glob: 13.0.3
+ graceful-fs: 4.2.11
+ node-gyp-build: 4.8.4
+ picomatch: 4.0.3
+ resolve-from: 5.0.0
+ transitivePeerDependencies:
+ - encoding
+ - rollup
+ - supports-color
+
+ '@vercel/node@5.6.3':
+ dependencies:
+ '@edge-runtime/node-utils': 2.3.0
+ '@edge-runtime/primitives': 4.1.0
+ '@edge-runtime/vm': 3.2.0
+ '@types/node': 20.11.0
+ '@vercel/build-utils': 13.4.0
+ '@vercel/error-utils': 2.0.3
+ '@vercel/nft': 1.1.1
+ '@vercel/static-config': 3.1.2
+ async-listen: 3.0.0
+ cjs-module-lexer: 1.2.3
+ edge-runtime: 2.5.9
+ es-module-lexer: 1.4.1
+ esbuild: 0.27.0
+ etag: 1.8.1
+ mime-types: 2.1.35
+ node-fetch: 2.6.9
+ path-to-regexp: 6.1.0
+ path-to-regexp-updated: path-to-regexp@6.3.0
+ ts-morph: 12.0.0
+ tsx: 4.21.0
+ typescript: 5.9.3
+ undici: 5.28.4
+ transitivePeerDependencies:
+ - encoding
+ - rollup
+ - supports-color
+
+ '@vercel/python-analysis@0.4.1':
+ dependencies:
+ '@bytecodealliance/preview2-shim': 0.17.6
+ '@renovatebot/pep440': 4.2.1
+ fs-extra: 11.1.1
+ js-yaml: 4.1.1
+ minimatch: 10.1.1
+ pip-requirements-js: 1.0.2
+ smol-toml: 1.5.2
+ zod: 3.22.4
+
+ '@vercel/static-config@3.1.2':
+ dependencies:
+ ajv: 8.6.3
+ json-schema-to-ts: 1.6.4
+ ts-morph: 12.0.0
+
+ abbrev@3.0.1: {}
+
+ acorn-import-attributes@1.9.5(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
+ acorn-jsx@5.3.2(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
+ acorn@8.15.0: {}
+
+ agent-base@7.1.4: {}
+
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
+ ajv@8.6.3:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+
+ any-promise@1.3.0: {}
+
+ arg@4.1.0: {}
+
+ argparse@2.0.1: {}
+
+ ast-types@0.13.4:
+ dependencies:
+ tslib: 2.8.1
+
+ async-listen@1.2.0: {}
+
+ async-listen@3.0.0: {}
+
+ async-listen@3.0.1: {}
+
+ async-retry@1.3.3:
+ dependencies:
+ retry: 0.13.1
+
+ async-sema@3.1.1: {}
+
+ asynckit@0.4.0: {}
+
+ balanced-match@1.0.2: {}
+
+ balanced-match@4.0.2:
+ dependencies:
+ jackspeak: 4.2.3
+
+ basic-ftp@5.1.0: {}
+
+ bindings@1.5.0:
+ dependencies:
+ file-uri-to-path: 1.0.0
+
+ brace-expansion@1.1.12:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.2:
+ dependencies:
+ balanced-match: 1.0.2
+
+ brace-expansion@5.0.2:
+ dependencies:
+ balanced-match: 4.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ buffer-crc32@0.2.13: {}
+
+ bytes@3.1.0: {}
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ chokidar@4.0.0:
+ dependencies:
+ readdirp: 4.1.2
+
+ chownr@3.0.0: {}
+
+ cjs-module-lexer@1.2.3: {}
+
+ code-block-writer@10.1.1: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ concat-map@0.0.1: {}
+
+ consola@3.4.2: {}
+
+ content-type@1.0.4: {}
+
+ convert-hrtime@3.0.0: {}
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ data-uri-to-buffer@6.0.2: {}
+
+ debug@4.3.4:
+ dependencies:
+ ms: 2.1.2
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ deep-is@0.1.4: {}
+
+ degenerator@5.0.1:
+ dependencies:
+ ast-types: 0.13.4
+ escodegen: 2.1.0
+ esprima: 4.0.1
+
+ delayed-stream@1.0.0: {}
+
+ depd@1.1.2: {}
+
+ detect-libc@2.1.2: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ edge-runtime@2.5.9:
+ dependencies:
+ '@edge-runtime/format': 2.2.1
+ '@edge-runtime/ponyfill': 2.4.2
+ '@edge-runtime/vm': 3.2.0
+ async-listen: 3.0.1
+ mri: 1.2.0
+ picocolors: 1.0.0
+ pretty-ms: 7.0.1
+ signal-exit: 4.0.2
+ time-span: 4.0.0
+
+ end-of-stream@1.1.0:
+ dependencies:
+ once: 1.3.3
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-module-lexer@1.4.1: {}
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-set-tostringtag@2.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ esbuild@0.27.0:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.27.0
+ '@esbuild/android-arm': 0.27.0
+ '@esbuild/android-arm64': 0.27.0
+ '@esbuild/android-x64': 0.27.0
+ '@esbuild/darwin-arm64': 0.27.0
+ '@esbuild/darwin-x64': 0.27.0
+ '@esbuild/freebsd-arm64': 0.27.0
+ '@esbuild/freebsd-x64': 0.27.0
+ '@esbuild/linux-arm': 0.27.0
+ '@esbuild/linux-arm64': 0.27.0
+ '@esbuild/linux-ia32': 0.27.0
+ '@esbuild/linux-loong64': 0.27.0
+ '@esbuild/linux-mips64el': 0.27.0
+ '@esbuild/linux-ppc64': 0.27.0
+ '@esbuild/linux-riscv64': 0.27.0
+ '@esbuild/linux-s390x': 0.27.0
+ '@esbuild/linux-x64': 0.27.0
+ '@esbuild/netbsd-arm64': 0.27.0
+ '@esbuild/netbsd-x64': 0.27.0
+ '@esbuild/openbsd-arm64': 0.27.0
+ '@esbuild/openbsd-x64': 0.27.0
+ '@esbuild/openharmony-arm64': 0.27.0
+ '@esbuild/sunos-x64': 0.27.0
+ '@esbuild/win32-arm64': 0.27.0
+ '@esbuild/win32-ia32': 0.27.0
+ '@esbuild/win32-x64': 0.27.0
+
+ escape-string-regexp@4.0.0: {}
+
+ escodegen@2.1.0:
+ dependencies:
+ esprima: 4.0.1
+ estraverse: 5.3.0
+ esutils: 2.0.3
+ optionalDependencies:
+ source-map: 0.6.1
+
+ eslint-scope@9.1.0:
+ dependencies:
+ '@types/esrecurse': 4.3.1
+ '@types/estree': 1.0.8
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint-visitor-keys@4.2.1: {}
+
+ eslint-visitor-keys@5.0.0: {}
+
+ eslint@10.0.0:
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.0)
+ '@eslint-community/regexpp': 4.12.2
+ '@eslint/config-array': 0.23.1
+ '@eslint/config-helpers': 0.5.2
+ '@eslint/core': 1.1.0
+ '@eslint/plugin-kit': 0.6.0
+ '@humanfs/node': 0.16.7
+ '@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.4.3
+ '@types/estree': 1.0.8
+ ajv: 6.12.6
+ cross-spawn: 7.0.6
+ debug: 4.4.3
+ escape-string-regexp: 4.0.0
+ eslint-scope: 9.1.0
+ eslint-visitor-keys: 5.0.0
+ espree: 11.1.0
+ esquery: 1.7.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 8.0.0
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ json-stable-stringify-without-jsonify: 1.0.1
+ minimatch: 10.2.0
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ transitivePeerDependencies:
+ - supports-color
+
+ espree@11.1.0:
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ eslint-visitor-keys: 5.0.0
+
+ esprima@4.0.1: {}
+
+ esquery@1.7.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@5.3.0: {}
+
+ estree-walker@2.0.2: {}
+
+ esutils@2.0.3: {}
+
+ etag@1.8.1: {}
+
+ events-intercept@2.0.0: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
+ fastq@1.20.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fd-slicer@1.1.0:
+ dependencies:
+ pend: 1.2.0
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ file-entry-cache@8.0.0:
+ dependencies:
+ flat-cache: 4.0.1
+
+ file-uri-to-path@1.0.0: {}
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flat-cache@4.0.1:
+ dependencies:
+ flatted: 3.3.3
+ keyv: 4.5.4
+
+ flatted@3.3.3: {}
+
+ form-data@4.0.5:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
+ mime-types: 2.1.35
+
+ fs-extra@11.1.1:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.2.0
+ universalify: 2.0.1
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ generic-pool@3.4.2: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ get-tsconfig@4.13.6:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
+ get-uri@6.0.5:
+ dependencies:
+ basic-ftp: 5.1.0
+ data-uri-to-buffer: 6.0.2
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob@13.0.3:
+ dependencies:
+ minimatch: 10.2.0
+ minipass: 7.1.2
+ path-scurry: 2.0.1
+
+ globals@17.3.0: {}
+
+ gopd@1.2.0: {}
+
+ graceful-fs@4.2.11: {}
+
+ has-symbols@1.1.0: {}
+
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ http-errors@1.7.3:
+ dependencies:
+ depd: 1.1.2
+ inherits: 2.0.4
+ setprototypeof: 1.1.1
+ statuses: 1.5.0
+ toidentifier: 1.0.0
+
+ http-proxy-agent@7.0.2:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ iconv-lite@0.4.24:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ ignore@5.3.2: {}
+
+ ignore@7.0.5: {}
+
+ imurmurhash@0.1.4: {}
+
+ inherits@2.0.4: {}
+
+ ip-address@10.1.0: {}
+
+ is-buffer@2.0.5: {}
+
+ is-extglob@2.1.1: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-node-process@1.2.0: {}
+
+ is-number@7.0.0: {}
+
+ isexe@2.0.0: {}
+
+ jackspeak@4.2.3:
+ dependencies:
+ '@isaacs/cliui': 9.0.0
+
+ jose@5.9.6: {}
+
+ js-yaml@4.1.1:
+ dependencies:
+ argparse: 2.0.1
+
+ json-buffer@3.0.1: {}
+
+ json-schema-to-ts@1.6.4:
+ dependencies:
+ '@types/json-schema': 7.0.15
+ ts-toolbelt: 6.15.5
+
+ json-schema-traverse@0.4.1: {}
+
+ json-schema-traverse@1.0.0: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ jsonfile@6.2.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ levn@0.4.1:
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ lru-cache@11.2.6: {}
+
+ lru-cache@6.0.0:
+ dependencies:
+ yallist: 4.0.0
+
+ lru-cache@7.18.3: {}
+
+ math-intrinsics@1.1.0: {}
+
+ merge2@1.4.1: {}
+
+ micro@9.3.5-canary.3:
+ dependencies:
+ arg: 4.1.0
+ content-type: 1.0.4
+ raw-body: 2.4.1
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ minimatch@10.1.1:
+ dependencies:
+ '@isaacs/brace-expansion': 5.0.1
+
+ minimatch@10.2.0:
+ dependencies:
+ brace-expansion: 5.0.2
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.12
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.2
+
+ minipass@7.1.2: {}
+
+ minizlib@3.1.0:
+ dependencies:
+ minipass: 7.1.2
+
+ mkdirp@1.0.4: {}
+
+ mri@1.2.0: {}
+
+ ms@2.1.1: {}
+
+ ms@2.1.2: {}
+
+ ms@2.1.3: {}
+
+ natural-compare@1.4.0: {}
+
+ netmask@2.0.2: {}
+
+ node-fetch@2.6.7:
+ dependencies:
+ whatwg-url: 5.0.0
+
+ node-fetch@2.6.9:
+ dependencies:
+ whatwg-url: 5.0.0
+
+ node-gyp-build@4.8.4: {}
+
+ nopt@8.1.0:
+ dependencies:
+ abbrev: 3.0.1
+
+ ohm-js@17.5.0: {}
+
+ once@1.3.3:
+ dependencies:
+ wrappy: 1.0.2
+
+ optionator@0.9.4:
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+
+ os-paths@4.4.0: {}
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ pac-proxy-agent@7.2.0:
+ dependencies:
+ '@tootallnate/quickjs-emscripten': 0.23.0
+ agent-base: 7.1.4
+ debug: 4.4.3
+ get-uri: 6.0.5
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ pac-resolver: 7.0.1
+ socks-proxy-agent: 8.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ pac-resolver@7.0.1:
+ dependencies:
+ degenerator: 5.0.1
+ netmask: 2.0.2
+
+ parse-ms@2.1.0: {}
+
+ path-browserify@1.0.1: {}
+
+ path-exists@4.0.0: {}
+
+ path-key@3.1.1: {}
+
+ path-scurry@2.0.1:
+ dependencies:
+ lru-cache: 11.2.6
+ minipass: 7.1.2
+
+ path-to-regexp@6.1.0: {}
+
+ path-to-regexp@6.3.0: {}
+
+ path-to-regexp@8.2.0: {}
+
+ pend@1.2.0: {}
+
+ picocolors@1.0.0: {}
+
+ picomatch@2.3.1: {}
+
+ picomatch@4.0.3: {}
+
+ pip-requirements-js@1.0.2:
+ dependencies:
+ ohm-js: 17.5.0
+
+ prelude-ls@1.2.1: {}
+
+ prettier@3.8.0: {}
+
+ pretty-ms@7.0.1:
+ dependencies:
+ parse-ms: 2.1.0
+
+ promisepipe@3.0.0: {}
+
+ proxy-agent@6.4.0:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ lru-cache: 7.18.3
+ pac-proxy-agent: 7.2.0
+ proxy-from-env: 1.1.0
+ socks-proxy-agent: 8.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ proxy-from-env@1.1.0: {}
+
+ punycode@2.3.1: {}
+
+ queue-microtask@1.2.3: {}
+
+ raw-body@2.4.1:
+ dependencies:
+ bytes: 3.1.0
+ http-errors: 1.7.3
+ iconv-lite: 0.4.24
+ unpipe: 1.0.0
+
+ readdirp@4.1.2: {}
+
+ require-from-string@2.0.2: {}
+
+ resolve-from@5.0.0: {}
+
+ resolve-pkg-maps@1.0.0: {}
+
+ retry@0.13.1: {}
+
+ reusify@1.1.0: {}
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safer-buffer@2.1.2: {}
+
+ semver@7.5.4:
+ dependencies:
+ lru-cache: 6.0.0
+
+ semver@7.7.4: {}
+
+ setprototypeof@1.1.1: {}
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ signal-exit@4.0.2: {}
+
+ smart-buffer@4.2.0: {}
+
+ smol-toml@1.5.2: {}
+
+ socks-proxy-agent@8.0.5:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ socks: 2.8.7
+ transitivePeerDependencies:
+ - supports-color
+
+ socks@2.8.7:
+ dependencies:
+ ip-address: 10.1.0
+ smart-buffer: 4.2.0
+
+ source-map@0.6.1:
+ optional: true
+
+ stat-mode@0.3.0: {}
+
+ statuses@1.5.0: {}
+
+ stream-to-array@2.3.0:
+ dependencies:
+ any-promise: 1.3.0
+
+ stream-to-promise@2.2.0:
+ dependencies:
+ any-promise: 1.3.0
+ end-of-stream: 1.1.0
+ stream-to-array: 2.3.0
+
+ tar@7.5.7:
+ dependencies:
+ '@isaacs/fs-minipass': 4.0.1
+ chownr: 3.0.0
+ minipass: 7.1.2
+ minizlib: 3.1.0
+ yallist: 5.0.0
+
+ throttleit@2.1.0: {}
+
+ time-span@4.0.0:
+ dependencies:
+ convert-hrtime: 3.0.0
+
+ tinyexec@0.3.2: {}
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ toidentifier@1.0.0: {}
+
+ tr46@0.0.3: {}
+
+ tree-kill@1.2.2: {}
+
+ ts-api-utils@2.4.0(typescript@5.9.3):
+ dependencies:
+ typescript: 5.9.3
+
+ ts-morph@12.0.0:
+ dependencies:
+ '@ts-morph/common': 0.11.1
+ code-block-writer: 10.1.1
+
+ ts-toolbelt@6.15.5: {}
+
+ tslib@2.8.1: {}
+
+ tsx@4.21.0:
+ dependencies:
+ esbuild: 0.27.0
+ get-tsconfig: 4.13.6
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ typescript@5.9.3: {}
+
+ uid-promise@1.0.0: {}
+
+ undici-types@5.26.5: {}
+
+ undici-types@7.16.0: {}
+
+ undici@5.28.4:
+ dependencies:
+ '@fastify/busboy': 2.1.1
+
+ universalify@2.0.1: {}
+
+ unpipe@1.0.0: {}
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ vercel@50.17.1(@vercel/node@5.6.3):
+ dependencies:
+ '@vercel/blob': 1.0.2
+ '@vercel/build-utils': 13.4.0
+ '@vercel/detect-agent': 1.1.0
+ '@vercel/fun': 1.3.0
+ chokidar: 4.0.0
+ esbuild: 0.27.0
+ form-data: 4.0.5
+ jose: 5.9.6
+ proxy-agent: 6.4.0
+ optionalDependencies:
+ '@vercel/node': 5.6.3
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+
+ webidl-conversions@3.0.1: {}
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ word-wrap@1.2.5: {}
+
+ wrappy@1.0.2: {}
+
+ xdg-app-paths@5.1.0:
+ dependencies:
+ xdg-portable: 7.3.0
+
+ xdg-portable@7.3.0:
+ dependencies:
+ os-paths: 4.4.0
+
+ yallist@4.0.0: {}
+
+ yallist@5.0.0: {}
+
+ yauzl-clone@1.0.4:
+ dependencies:
+ events-intercept: 2.0.0
+
+ yauzl-promise@2.1.3:
+ dependencies:
+ yauzl: 2.10.0
+ yauzl-clone: 1.0.4
+
+ yauzl@2.10.0:
+ dependencies:
+ buffer-crc32: 0.2.13
+ fd-slicer: 1.1.0
+
+ yocto-queue@0.1.0: {}
+
+ zod@3.22.4: {}
diff --git a/sandbox/README.md b/sandbox/README.md
new file mode 100644
index 0000000..d929b9c
--- /dev/null
+++ b/sandbox/README.md
@@ -0,0 +1,169 @@
+# Sandbox Testing Scripts
+
+This folder contains standalone test scripts to validate the GitHub Flex functionality without deploying to Vercel.
+
+## โ๏ธ Prerequisites
+
+1. Build the TypeScript code first:
+ ```bash
+ pnpm build
+ # or: npm run build
+ ```
+
+2. (Optional) Set your GitHub token:
+ ```bash
+ export GITHUB_TOKEN=your_token_here
+ ```
+
+## ๐งช Available Test Scripts
+
+### 1. Test Stats Fetcher
+
+Tests the GitHub stats fetching functionality:
+
+```bash
+node sandbox/test-stats.js [username]
+```
+
+**Examples:**
+
+```bash
+node sandbox/test-stats.js torvalds
+node sandbox/test-stats.js octocat
+```
+
+---
+
+### 2. Test Language Stats
+
+Tests the language statistics fetching:
+
+```bash
+node sandbox/test-languages.js [username] [count]
+```
+
+**Examples:**
+
+```bash
+node sandbox/test-languages.js torvalds
+node sandbox/test-languages.js octocat 8
+```
+
+**Output:**
+
+- Top N languages by bytes
+- Percentage breakdown
+
+---
+
+### 3. Test Language SVG Generation
+
+Generates language stats SVG files that you can open in a browser:
+
+```bash
+node sandbox/test-languages-svg.js [username] [theme] [count] [exclude]
+```
+
+**Examples:**
+
+```bash
+node sandbox/test-languages-svg.js torvalds dark 8
+node sandbox/test-languages-svg.js octocat tokyonight 5 "HTML,CSS"
+```
+
+**Output:**
+
+- SVG file saved to `sandbox/output-{username}-languages-{theme}.svg`
+- Open the file in any web browser to view the badge
+
+---
+
+### 4. Test SVG Generation
+
+Generates actual SVG files that you can open in a browser:
+
+```bash
+node sandbox/test-svg.js [username] [theme]
+```
+
+**Examples:**
+
+```bash
+node sandbox/test-svg.js torvalds dark
+node sandbox/test-svg.js octocat tokyonight
+```
+
+**Available themes:**
+
+- `default` - Warm playful theme with hand-written feel
+- `dark` - Dark mode with vibrant accents
+- `radical` - Pink and cyan cyberpunk
+- `merko` - Green terminal vibes
+- `gruvbox` - Retro warm colors
+- `tokyonight` - Cyberpunk aesthetics
+- `bubblegum` - Pink and purple playful
+- `ocean` - Blue aquatic theme
+
+**Output:**
+
+- SVG file saved to `sandbox/output-{username}-{theme}.svg`
+- Open the file in any web browser to view the badge
+
+---
+
+### 5. Test Mock Stats SVG (No API Required)
+
+Generates stats SVG files with mock data (useful when GitHub API is rate-limited):
+
+```bash
+node sandbox/test-stats-mock.js
+```
+
+**Output:**
+
+- Generates SVG files for all themes with mock data
+- No GitHub API calls required
+- Perfect for testing styling changes
+
+---
+
+## ๐ง Troubleshooting
+
+### "Cannot find module" error
+
+Make sure you've built the TypeScript code:
+
+```bash
+pnpm build
+# or: npm run build
+```
+
+### Rate limit errors
+
+Set a GitHub token to increase rate limits:
+
+```bash
+export GITHUB_TOKEN=your_token_here
+```
+
+Or create a `.env` file in the project root:
+
+```
+GITHUB_TOKEN=your_token_here
+```
+
+---
+
+## ๐ฏ Next Steps
+
+Once you've verified everything works locally with these test scripts, you can:
+
+1. **Run with Vercel CLI** for full endpoint testing:
+ ```bash
+ pnpm dev
+ # or: npm run dev
+ ```
+
+2. **Deploy to Vercel** for production use
+
+3. **Use the badges** in your GitHub profile README
diff --git a/sandbox/test-languages-svg.js b/sandbox/test-languages-svg.js
new file mode 100644
index 0000000..ee78929
--- /dev/null
+++ b/sandbox/test-languages-svg.js
@@ -0,0 +1,80 @@
+/**
+ * Test script for language stats SVG card generation
+ * Run with: node sandbox/test-languages-svg.js
+ *
+ * This will generate SVG files that you can open in a browser
+ */
+
+import { writeFileSync } from "fs";
+import { fetchLanguageStats, getTopLanguages } from "../dist/lib/languages.js";
+import { generateCard, generateLanguageItem } from "../dist/lib/card.js";
+import { ThemeName } from "../dist/lib/types.js";
+import { themes } from "../dist/lib/themes.js";
+
+async function testLanguagesSVG() {
+ console.log("Testing Language Stats SVG Generation\n");
+ console.log("=".repeat(50));
+
+ const username = process.argv[2] || "torvalds";
+ const themeArg = process.argv[3] || "default";
+ const theme = Object.values(ThemeName).includes(themeArg)
+ ? themeArg
+ : ThemeName.Default;
+ const count = parseInt(process.argv[4]) || 5;
+ const exclude = process.argv[5] || "";
+ const token = process.env.GITHUB_TOKEN;
+
+ console.log(`\nGenerating language stats card for: ${username}`);
+ console.log(`Theme: ${theme}`);
+ console.log(`Languages to show: ${count}`);
+ if (exclude) {
+ console.log(`Excluding: ${exclude}`);
+ }
+
+ try {
+ console.log("\nFetching language stats...");
+ const stats = await fetchLanguageStats(username, token, exclude);
+ const topLanguages = getTopLanguages(stats, count);
+
+ if (topLanguages.length === 0) {
+ throw new Error("No languages found");
+ }
+
+ console.log("Generating SVG card...");
+ const colors = themes[theme];
+
+ // Generate language items with playful card styling
+ const languageItems = topLanguages
+ .map((lang, index) =>
+ generateLanguageItem(
+ lang.name,
+ lang.percent,
+ index,
+ colors.icon,
+ colors.border,
+ ),
+ )
+ .join("");
+
+ const cardHeight = 90 + topLanguages.length * 50;
+
+ const svg = generateCard(languageItems, {
+ title: "Most Used Languages",
+ width: 450,
+ height: cardHeight,
+ theme: theme,
+ hideBorder: false,
+ });
+
+ const filename = `sandbox/output-${username}-languages-${theme}.svg`;
+ writeFileSync(filename, svg);
+
+ console.log(`\nโ
Success! SVG saved to: ${filename}`);
+ console.log("Open this file in a browser to view the badge\n");
+ } catch (error) {
+ console.error("\nโ Error:", error.message);
+ process.exit(1);
+ }
+}
+
+testLanguagesSVG();
diff --git a/sandbox/test-languages.js b/sandbox/test-languages.js
new file mode 100644
index 0000000..2dde977
--- /dev/null
+++ b/sandbox/test-languages.js
@@ -0,0 +1,55 @@
+/**
+ * Test script for language stats functionality
+ * Run with: node sandbox/test-languages.js
+ */
+
+import { fetchLanguageStats, getTopLanguages } from "../lib/languages.js";
+
+async function testLanguageStats() {
+ console.log("Testing Language Stats Fetcher\n");
+ console.log("=".repeat(50));
+
+ const username = process.argv[2] || "torvalds";
+ const count = parseInt(process.argv[3]) || 5;
+ const token = process.env.GITHUB_TOKEN;
+
+ console.log(`\nFetching language stats for: ${username}`);
+ console.log(`Top languages to show: ${count}`);
+
+ if (token) {
+ console.log("Using GitHub token for higher rate limits");
+ } else {
+ console.log("No GitHub token found - using unauthenticated requests");
+ console.log(
+ "Set GITHUB_TOKEN environment variable for higher rate limits\n",
+ );
+ }
+
+ try {
+ const startTime = Date.now();
+ const stats = await fetchLanguageStats(username, token);
+ const topLanguages = getTopLanguages(stats, count);
+ const endTime = Date.now();
+
+ console.log(
+ "\nโ
Success! Language stats fetched in",
+ endTime - startTime,
+ "ms\n",
+ );
+ console.log("Top Languages:");
+
+ topLanguages.forEach((lang, index) => {
+ console.log(` ${index + 1}. ${lang.name}`);
+ console.log(
+ ` ${lang.percent.toFixed(2)}% (${lang.bytes.toLocaleString()} bytes)`,
+ );
+ });
+
+ console.log(`\nTotal languages found: ${Object.keys(stats).length}`);
+ } catch (error) {
+ console.error("\nโ Error:", error.message);
+ process.exit(1);
+ }
+}
+
+testLanguageStats();
diff --git a/sandbox/test-stats-mock.js b/sandbox/test-stats-mock.js
new file mode 100644
index 0000000..d242a22
--- /dev/null
+++ b/sandbox/test-stats-mock.js
@@ -0,0 +1,43 @@
+/**
+ * Test script for stats SVG generation with mock data
+ * Run with: node sandbox/test-stats-mock.js
+ */
+
+import { writeFileSync } from "fs";
+import { generateCard, generateStatItem } from "../dist/lib/card.js";
+import { ThemeName } from "../dist/lib/types.js";
+
+console.log("Generating mock stats card...\n");
+
+// Mock stats data
+const statItems = [
+ generateStatItem("Total Stars", "1,234", 0),
+ generateStatItem("Total Commits", "5,678", 1),
+ generateStatItem("Total PRs", "432", 2),
+ generateStatItem("Total Issues", "89", 3),
+ generateStatItem("Total Repos", "56", 4),
+].join("");
+
+// Test with different themes
+const themes = [
+ ThemeName.Default,
+ ThemeName.Dark,
+ ThemeName.Bubblegum,
+ ThemeName.Ocean,
+];
+
+themes.forEach((theme) => {
+ const svg = generateCard(statItems, {
+ title: `Test User's GitHub Stats`,
+ width: 500,
+ height: 240,
+ theme: theme,
+ hideBorder: false,
+ });
+
+ const filename = `sandbox/output-mock-stats-${theme}.svg`;
+ writeFileSync(filename, svg);
+ console.log(`โ
Generated: ${filename}`);
+});
+
+console.log("\nโจ Done! Open the SVG files in your browser to view them.\n");
diff --git a/sandbox/test-stats.js b/sandbox/test-stats.js
new file mode 100644
index 0000000..b72c746
--- /dev/null
+++ b/sandbox/test-stats.js
@@ -0,0 +1,45 @@
+/**
+ * Test script for GitHub stats functionality
+ * Run with: node sandbox/test-stats.js
+ */
+
+import { fetchGitHubStats } from "../lib/github.js";
+
+async function testStats() {
+ console.log("Testing GitHub Stats Fetcher\n");
+ console.log("=".repeat(50));
+
+ const username = process.argv[2] || "torvalds";
+ const token = process.env.GITHUB_TOKEN;
+
+ console.log(`\nFetching stats for: ${username}`);
+ if (token) {
+ console.log("Using GitHub token for higher rate limits");
+ } else {
+ console.log("No GitHub token found - using unauthenticated requests");
+ console.log(
+ "Set GITHUB_TOKEN environment variable for higher rate limits\n",
+ );
+ }
+
+ try {
+ const startTime = Date.now();
+ const stats = await fetchGitHubStats(username, token);
+ const endTime = Date.now();
+
+ console.log("\nโ
Success! Stats fetched in", endTime - startTime, "ms\n");
+ console.log("Results:");
+ console.log(" Username:", stats.username);
+ console.log(" Total Stars:", stats.totalStars.toLocaleString());
+ console.log(" Total Commits:", stats.totalCommits.toLocaleString());
+ console.log(" Total PRs:", stats.totalPRs.toLocaleString());
+ console.log(" Total Issues:", stats.totalIssues.toLocaleString());
+ console.log(" Total Repos:", stats.contributedTo.toLocaleString());
+ console.log(" Rank:", stats.rank);
+ } catch (error) {
+ console.error("\nโ Error:", error.message);
+ process.exit(1);
+ }
+}
+
+testStats();
diff --git a/sandbox/test-svg.js b/sandbox/test-svg.js
new file mode 100644
index 0000000..96b5b36
--- /dev/null
+++ b/sandbox/test-svg.js
@@ -0,0 +1,59 @@
+/**
+ * Test script for SVG card generation
+ * Run with: node sandbox/test-svg.js
+ *
+ * This will generate SVG files that you can open in a browser
+ */
+
+import { writeFileSync } from "fs";
+import { fetchGitHubStats } from "../lib/github.js";
+import { generateCard, generateStatItem } from "../lib/card.js";
+import { ThemeName } from "../lib/types.js";
+
+async function testSVGGeneration() {
+ console.log("Testing SVG Card Generation\n");
+ console.log("=".repeat(50));
+
+ const username = process.argv[2] || "torvalds";
+ const themeArg = process.argv[3] || "default";
+ const theme = Object.values(ThemeName).includes(themeArg)
+ ? themeArg
+ : ThemeName.Default;
+ const token = process.env.GITHUB_TOKEN;
+
+ console.log(`\nGenerating stats card for: ${username}`);
+ console.log(`Theme: ${theme}`);
+
+ try {
+ console.log("\nFetching GitHub stats...");
+ const stats = await fetchGitHubStats(username, token);
+
+ console.log("Generating SVG card...");
+ const statItems = [
+ generateStatItem("Total Stars", stats.totalStars.toLocaleString(), 0),
+ generateStatItem("Total Commits", stats.totalCommits.toLocaleString(), 1),
+ generateStatItem("Total PRs", stats.totalPRs.toLocaleString(), 2),
+ generateStatItem("Total Issues", stats.totalIssues.toLocaleString(), 3),
+ generateStatItem("Total Repos", stats.contributedTo.toLocaleString(), 4),
+ ].join("");
+
+ const svg = generateCard(statItems, {
+ title: `${username}'s GitHub Stats`,
+ width: 500,
+ height: 240,
+ theme: theme,
+ hideBorder: false,
+ });
+
+ const filename = `sandbox/output-${username}-${theme}.svg`;
+ writeFileSync(filename, svg);
+
+ console.log(`\nโ
Success! SVG saved to: ${filename}`);
+ console.log("Open this file in a browser to view the badge\n");
+ } catch (error) {
+ console.error("\nโ Error:", error.message);
+ process.exit(1);
+ }
+}
+
+testSVGGeneration();
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..c4bc463
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "ES2020",
+ "lib": ["ES2020", "DOM"],
+ "outDir": "./dist",
+ "rootDir": "./",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "moduleResolution": "node"
+ },
+ "include": ["api/**/*", "lib/**/*"],
+ "exclude": ["node_modules"]
+}
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..cff7613
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,23 @@
+{
+ "functions": {
+ "api/**/*.ts": {
+ "memory": 1024,
+ "maxDuration": 10
+ }
+ },
+ "headers": [
+ {
+ "source": "/api/(.*)",
+ "headers": [
+ {
+ "key": "Access-Control-Allow-Origin",
+ "value": "*"
+ },
+ {
+ "key": "Access-Control-Allow-Methods",
+ "value": "GET"
+ }
+ ]
+ }
+ ]
+}