├── api ├── resources.json ├── _regions.ts ├── _db.ts ├── get.ts ├── stats.ts ├── facets.ts ├── edge │ ├── cpt1.ts │ ├── dub1.ts │ ├── lhr1.ts │ ├── pdx1.ts │ ├── arn1.ts │ ├── bom1.ts │ ├── cdg1.ts │ ├── cle1.ts │ ├── fra1.ts │ ├── gru1.ts │ ├── hnd1.ts │ ├── iad1.ts │ ├── icn1.ts │ ├── kix1.ts │ ├── sfo1.ts │ ├── sin1.ts │ ├── syd1.ts │ └── hkg1.ts ├── _notifications.ts ├── _requests.ts ├── _ping.ts ├── cron.ts └── index.ts ├── public ├── favicon.ico └── requests.json ├── tsconfig.json ├── package.json ├── vercel.json ├── .gitignore ├── .github └── workflows │ └── ping.yml ├── tb ├── datasources │ └── http_ping_responses.datasource └── pipes │ ├── endpoint__get_http_facets.pipe │ ├── endpoint__get_http_stats.pipe │ └── endpoint__get_http.pipe ├── .env.example ├── README.md └── pnpm-lock.yaml /api/resources.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/vercel-edge-ping/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/requests.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "url": "https://openstat.us/200", 4 | "method": "GET" 5 | } 6 | ] -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "skipLibCheck": true, 8 | "strict": true 9 | }, 10 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/vercel-edge-ping", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vercel dev", 6 | "deploy": "vercel", 7 | "deploy:prod": "vercel --prod" 8 | }, 9 | "dependencies": { 10 | "@vercel/functions": "^1.5.0" 11 | }, 12 | "devDependencies": { 13 | "@types/node": "^22.9.0", 14 | "typescript": "^5.6.3", 15 | "vercel": "^32.4.1" 16 | } 17 | } -------------------------------------------------------------------------------- /api/_regions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * List of all regions you'd like to ping. 3 | * @link https://vercel.com/docs/edge-network/regions#region-list 4 | */ 5 | export const regions = [ 6 | "arn1", 7 | "bom1", 8 | "cdg1", 9 | "cle1", 10 | "cpt1", 11 | "dub1", 12 | "fra1", 13 | "gru1", 14 | "hkg1", 15 | "hnd1", 16 | "iad1", 17 | "icn1", 18 | "kix1", 19 | "lhr1", 20 | "pdx1", 21 | "sfo1", 22 | "sin1", 23 | "syd1", 24 | ]; 25 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "redirects": [ 3 | { 4 | "source": "/", 5 | "destination": "/api", 6 | "permanent": true 7 | } 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "/api/(.*)", 12 | "destination": "/api" 13 | } 14 | ], 15 | "functions": { 16 | "api/cron.ts": { 17 | "maxDuration": 60 18 | } 19 | }, 20 | "crons": [ 21 | { 22 | "path": "/api/cron", 23 | "schedule": "0 0 * * *" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # dev 2 | .vercel/ 3 | .yarn/ 4 | !.yarn/releases 5 | .vscode/* 6 | !.vscode/launch.json 7 | !.vscode/*.code-snippets 8 | .idea/workspace.xml 9 | .idea/usage.statistics.xml 10 | .idea/shelf 11 | 12 | # deps 13 | node_modules/ 14 | 15 | # env 16 | .env 17 | .env.production 18 | 19 | # logs 20 | logs/ 21 | *.log 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | pnpm-debug.log* 26 | lerna-debug.log* 27 | 28 | # misc 29 | .DS_Store 30 | .vercel 31 | .env*.local 32 | 33 | # tb 34 | .tinyb 35 | .venv -------------------------------------------------------------------------------- /.github/workflows/ping.yml: -------------------------------------------------------------------------------- 1 | name: Ping Endpoint 2 | 3 | on: 4 | # schedule: 5 | # - cron: "*/10 * * * *" # Every 10 minutes 6 | workflow_dispatch: # Allows manual trigger from the GitHub Actions UI 7 | 8 | jobs: 9 | ping-endpoint: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Send Request to Endpoint 14 | run: | 15 | curl -X GET $BASE_URL/api/cron \ 16 | -H "Authorization: Bearer $CRON_SECRET" 17 | env: 18 | CRON_SECRET: ${{ secrets.CRON_SECRET }} 19 | BASE_URL: ${{ secrets.BASE_URL }} 20 | -------------------------------------------------------------------------------- /tb/datasources/http_ping_responses.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | SCHEMA > 4 | `url` String `json:$.url`, 5 | `method` String `json:$.method`, 6 | `timestamp` Int64 `json:$.timestamp`, 7 | `region` LowCardinality(String) `json:$.region`, 8 | `latency` Nullable(Int64) `json:$.latency`, 9 | `status` Nullable(Int16) `json:$.status`, 10 | `error` Nullable(String) `json:$.error`, 11 | `headers` Nullable(String) `json:$.headers`, 12 | `body` Nullable(String) `json:$.body` 13 | 14 | ENGINE "MergeTree" 15 | ENGINE_SORTING_KEY "url, timestamp" 16 | ENGINE_PARTITION_KEY "toYYYYMM(fromUnixTimestamp64Milli(timestamp))" -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | CRON_SECRET="XXX" 2 | PING_SECRET="XXX" 3 | 4 | # optional 5 | TINYBIRD_TOKEN="p.XXX" 6 | # optional 7 | SLACK_WEBHOOK_URL="https://hooks.slack.com/services/XXX/XXX/XXX" 8 | # optional 9 | DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/XXX/XXX/XXX" 10 | # optional 11 | CAMPSITE_API_KEY="XXX" 12 | CAMPSITE_CHANNEL_ID="XX" 13 | 14 | # optional 15 | TELEGRAM_BOT_TOKEN="XXX:XXX" 16 | TELEGRAM_CHAT_ID="XXX" 17 | 18 | # optional 19 | EXTERNAL_REQUESTS_URL="http://localhost:3000/requests.json" 20 | EXTERNAL_REQUESTS_SECRET="XXX" 21 | 22 | # optional 23 | REQUESTS='[{"url":"https://openstat.us/200","method":"GET"}]' 24 | 25 | # overriding the default value 26 | BASE_URL= -------------------------------------------------------------------------------- /tb/pipes/endpoint__get_http_facets.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | NODE endpoint 4 | SQL > 5 | 6 | % 7 | SELECT facet, value, COUNT(*) AS count 8 | FROM 9 | ( 10 | SELECT 11 | arrayJoin( 12 | [ 13 | ('method', method), 14 | ('url', url), 15 | ('status', toString(status)), 16 | ('region', region), 17 | ('latency', toString(latency)), 18 | ('level', level) 19 | ] 20 | ) AS pair, 21 | pair .1 AS facet, 22 | pair .2 AS value 23 | FROM endpoint__get_http__v0 24 | ) 25 | GROUP BY facet, value -------------------------------------------------------------------------------- /api/_db.ts: -------------------------------------------------------------------------------- 1 | import type { PingResponse } from "./_ping"; 2 | 3 | const DATASOURCE_NAME = "http_ping_responses__v0"; 4 | 5 | export async function ingest( 6 | requests: PingResponse[] 7 | ): Promise { 8 | if (!process.env.TINYBIRD_TOKEN) return; 9 | 10 | const body = requests 11 | // REMINDER: avoid nested objects like `headers` in the payload - instead stringify them 12 | .map((p) => JSON.stringify({ ...p, headers: JSON.stringify(p.headers) })) 13 | .join("\n"); 14 | 15 | const res = await fetch( 16 | `https://api.tinybird.co/v0/events?name=${DATASOURCE_NAME}&wait=true`, 17 | { 18 | method: "POST", 19 | headers: { 20 | "Content-Type": "application/json", 21 | Authorization: `Bearer ${process.env.TINYBIRD_TOKEN}`, 22 | }, 23 | body, 24 | } 25 | ); 26 | 27 | return res; 28 | } 29 | -------------------------------------------------------------------------------- /api/get.ts: -------------------------------------------------------------------------------- 1 | const EVENT_NAME = "endpoint__get_http__v0"; 2 | 3 | export async function GET(req: Request) { 4 | if (!process.env.TINYBIRD_TOKEN) { 5 | return new Response("No Connected Database", { status: 200 }); 6 | } 7 | 8 | const reqUrl = new URL(req.url); 9 | const searchParams = reqUrl.searchParams; 10 | 11 | const tbUrl = new URL( 12 | `https://api.tinybird.co/v0/pipes/${EVENT_NAME}.json?${searchParams.toString()}` 13 | ); 14 | 15 | const result = await fetch(tbUrl, { 16 | method: "GET", 17 | headers: { 18 | Authorization: `Bearer ${process.env.TINYBIRD_TOKEN}`, 19 | }, 20 | }) 21 | .then((r) => r.json()) 22 | .then((r) => r) 23 | .catch((e) => e.toString()); 24 | 25 | if (!result?.data) { 26 | console.error(`Error with: ${JSON.stringify(result)}`); 27 | return new Response("Internal Server Error", { status: 500 }); 28 | } 29 | 30 | return new Response(JSON.stringify(result), { 31 | headers: { "Content-Type": "application/json" }, 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /api/stats.ts: -------------------------------------------------------------------------------- 1 | const EVENT_NAME = "endpoint__get_http_stats__v0"; 2 | 3 | export async function GET(req: Request) { 4 | if (!process.env.TINYBIRD_TOKEN) { 5 | return new Response("No Connected Database", { status: 200 }); 6 | } 7 | 8 | const reqUrl = new URL(req.url); 9 | const searchParams = reqUrl.searchParams; 10 | 11 | const tbUrl = new URL( 12 | `https://api.tinybird.co/v0/pipes/${EVENT_NAME}.json?${searchParams.toString()}` 13 | ); 14 | 15 | const result = await fetch(tbUrl, { 16 | method: "GET", 17 | headers: { 18 | Authorization: `Bearer ${process.env.TINYBIRD_TOKEN}`, 19 | }, 20 | }) 21 | .then((r) => r.json()) 22 | .then((r) => r) 23 | .catch((e) => e.toString()); 24 | 25 | if (!result?.data) { 26 | console.error(`Error with: ${JSON.stringify(result)}`); 27 | return new Response("Internal Server Error", { status: 500 }); 28 | } 29 | 30 | return new Response(JSON.stringify(result), { 31 | headers: { "Content-Type": "application/json" }, 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /api/facets.ts: -------------------------------------------------------------------------------- 1 | const EVENT_NAME = "endpoint__get_http_facets__v0"; 2 | 3 | export async function GET(req: Request) { 4 | if (!process.env.TINYBIRD_TOKEN) { 5 | return new Response("No Connected Database", { status: 200 }); 6 | } 7 | 8 | const reqUrl = new URL(req.url); 9 | const searchParams = reqUrl.searchParams; 10 | 11 | const tbUrl = new URL( 12 | `https://api.tinybird.co/v0/pipes/${EVENT_NAME}.json?${searchParams.toString()}` 13 | ); 14 | 15 | const result = await fetch(tbUrl, { 16 | method: "GET", 17 | headers: { 18 | Authorization: `Bearer ${process.env.TINYBIRD_TOKEN}`, 19 | }, 20 | }) 21 | .then((r) => r.json()) 22 | .then((r) => r) 23 | .catch((e) => e.toString()); 24 | 25 | if (!result?.data) { 26 | console.error(`Error with: ${JSON.stringify(result)}`); 27 | return new Response("Internal Server Error", { status: 500 }); 28 | } 29 | 30 | return new Response(JSON.stringify(result), { 31 | headers: { "Content-Type": "application/json" }, 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /api/edge/cpt1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["cpt1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | await ingest([res]); 31 | 32 | return new Response(JSON.stringify(res), { 33 | headers: { "Content-Type": "application/json" }, 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /api/edge/dub1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["dub1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | await ingest([res]); 31 | 32 | return new Response(JSON.stringify(res), { 33 | headers: { "Content-Type": "application/json" }, 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /api/edge/lhr1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["lhr1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | await ingest([res]); 31 | 32 | return new Response(JSON.stringify(res), { 33 | headers: { "Content-Type": "application/json" }, 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /api/edge/pdx1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["pdx1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | await ingest([res]); 31 | 32 | return new Response(JSON.stringify(res), { 33 | headers: { "Content-Type": "application/json" }, 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /api/edge/arn1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["arn1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/bom1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["bom1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/cdg1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["cdg1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/cle1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["cle1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/fra1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["fra1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/gru1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["gru1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/hnd1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["hnd1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/iad1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["iad1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/icn1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["icn1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/kix1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["kix1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/sfo1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["sfo1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/sin1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["sin1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/syd1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["syd1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/edge/hkg1.ts: -------------------------------------------------------------------------------- 1 | import { getEnv, waitUntil } from "@vercel/functions"; 2 | import { ping } from "../_ping"; 3 | import { ingest } from "../_db"; 4 | 5 | export const config = { 6 | runtime: "edge", 7 | regions: ["hkg1"], 8 | }; 9 | 10 | export default async function handler(req: Request): Promise { 11 | const { VERCEL_REGION } = getEnv(); 12 | const region = VERCEL_REGION || "unknown"; 13 | const authHeader = req.headers.get("authorization"); 14 | 15 | if ( 16 | !process.env.PING_SECRET || 17 | authHeader !== `Bearer ${process.env.PING_SECRET}` 18 | ) { 19 | return new Response("Unauthorized", { status: 401 }); 20 | } 21 | 22 | if (req.method !== "POST") { 23 | return new Response(`Method Not Allowed ('${region}')`, { status: 405 }); 24 | } 25 | 26 | const body = await req.json(); 27 | const res = await ping(body); 28 | 29 | console.log("Ping response", region, res); 30 | 31 | await ingest([res]); 32 | 33 | return new Response(JSON.stringify(res), { 34 | headers: { "Content-Type": "application/json" }, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /tb/pipes/endpoint__get_http_stats.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | NODE endpoint 4 | SQL > 5 | 6 | % 7 | WITH 8 | filtered_data AS ( 9 | SELECT timestamp, status FROM endpoint 10 | {% if defined(timestampStart) and defined(timestampEnd) %} 11 | UNION ALL 12 | SELECT {{ Int64(timestampStart) }} AS timestamp, 0 AS status -- Start boundary 13 | UNION ALL 14 | SELECT {{ Int64(timestampEnd) }} AS timestamp, 0 AS status -- End boundary 15 | {% end %} 16 | ) 17 | SELECT 18 | toUnixTimestamp( 19 | toStartOfInterval( 20 | toDateTime(timestamp / 1000), INTERVAL {{ Int32(interval, 1_440) }} MINUTE 21 | ) 22 | ) * 1000 AS timestamp, 23 | countIf(status >= 200 AND status < 400) AS success, 24 | countIf(status >= 400 AND status < 500) AS warning, 25 | countIf(status >= 500) AS error 26 | FROM filtered_data 27 | GROUP BY timestamp 28 | ORDER BY timestamp 29 | WITH FILL STEP {{ Int32(interval, 1_440) }} * 60 * 1000 -------------------------------------------------------------------------------- /api/_notifications.ts: -------------------------------------------------------------------------------- 1 | export async function sendSlackMessage(message: string) { 2 | if (!process.env.SLACK_WEBHOOK_URL) return; 3 | return fetch(process.env.SLACK_WEBHOOK_URL, { 4 | method: "POST", 5 | headers: { 6 | "Content-Type": "application/json", 7 | }, 8 | body: JSON.stringify({ text: message }), 9 | }); 10 | } 11 | 12 | export async function sendDiscordMessage(message: string) { 13 | if (!process.env.DISCORD_WEBHOOK_URL) return; 14 | return fetch(process.env.DISCORD_WEBHOOK_URL, { 15 | method: "POST", 16 | headers: { 17 | "Content-Type": "application/json", 18 | }, 19 | body: JSON.stringify({ content: message }), 20 | }); 21 | } 22 | 23 | export async function sendCampsiteMessage(message: string) { 24 | if (!process.env.CAMPSITE_API_KEY || !process.env.CAMPSITE_CHANNEL_ID) return; 25 | return fetch("https://api.campsite.com/v2/posts", { 26 | method: "POST", 27 | headers: { 28 | "Content-Type": "application/json", 29 | Authorization: `Bearer ${process.env.CAMPSITE_API_KEY}`, 30 | }, 31 | body: JSON.stringify({ 32 | channel_id: process.env.CAMPSITE_CHANNEL_ID, 33 | content_markdown: message, 34 | }), 35 | }); 36 | } 37 | 38 | export async function sendTelegramMessage(message: string) { 39 | if (!process.env.TELEGRAM_BOT_TOKEN || !process.env.TELEGRAM_CHAT_ID) return; 40 | return fetch( 41 | `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendMessage?chat_id=${process.env.TELEGRAM_CHAT_ID}&text=${message}` 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /tb/pipes/endpoint__get_http.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | NODE endpoint 4 | SQL > 5 | 6 | % 7 | SELECT 8 | *, 9 | multiIf( 10 | status >= 200 AND status < 400, 11 | 'success', 12 | status >= 400 AND status < 500, 13 | 'warning', 14 | status >= 500, 15 | 'error', 16 | 'unknown' -- Default case if none of the above match 17 | ) as level 18 | from http_ping_responses__v0 19 | WHERE 20 | 1 = 1 21 | {% if defined(latencyStart) %} AND latency >= {{ Int32(latencyStart) }} {% end %} 22 | {% if defined(latencyEnd) %} AND latency <= {{ Int32(latencyEnd) }} {% end %} 23 | {% if defined(statuses) %} AND status in {{ Array(statuses, Int16) }} {% end %} 24 | {% if defined(regions) %} AND region in {{ Array(regions, String) }} {% end %} 25 | {% if defined(methods) %} AND method in {{ Array(methods, String) }} {% end %} 26 | {% if defined(url) %} AND url ILIKE concat('%', {{ String(url) }}, '%') {% end %} 27 | {% if defined(timestampStart) %} AND timestamp >= {{ Int64(timestampStart) }} {% end %} 28 | {% if defined(timestampEnd) %} AND timestamp <= {{ Int64(timestampEnd) }} {% end %} 29 | {% if defined(levels) %} 30 | AND multiIf( 31 | status >= 200 AND status < 400, 32 | 'success', 33 | status >= 400 AND status < 500, 34 | 'warning', 35 | status >= 500, 36 | 'error', 37 | 'unknown' 38 | ) 39 | IN {{ Array(levels, String) }} 40 | {% end %} 41 | ORDER BY 42 | {{ column(orderBy, 'timestamp') }} 43 | {% if defined(orderDir) and String(orderDir) == "ASC" %} ASC 44 | {% else %} DESC 45 | {% end %} 46 | {% if defined(pageSize) %} LIMIT {{ Int32(pageSize, 100) }} {% end %} 47 | OFFSET {{ Int32(pageIndex, 0) * Int32(pageSize, 100) }} -------------------------------------------------------------------------------- /api/_requests.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | import type { PingRequest } from "./_ping"; 4 | 5 | /** 6 | * 7 | * @returns List of file requests to ping from resources.json. 8 | */ 9 | export const getFileRequests = (): PingRequest[] => { 10 | const resourcesPath = path.join(process.cwd(), "./api/resources.json"); 11 | const file = fs.readFileSync(resourcesPath); 12 | const data = JSON.parse(file.toString()); 13 | 14 | if (!validateData(data)) { 15 | console.error("Invalid resources.json file."); 16 | return []; 17 | } 18 | 19 | return data; 20 | }; 21 | 22 | /** 23 | * 24 | * @returns List of external requests to ping. 25 | */ 26 | export async function getExternalRequests(): Promise { 27 | if (!process.env.EXTERNAL_REQUESTS_URL) return []; 28 | 29 | const res = await fetch(process.env.EXTERNAL_REQUESTS_URL, { 30 | headers: { 31 | Authorization: `Bearer ${process.env.EXTERNAL_REQUESTS_SECRET}`, 32 | }, 33 | }); 34 | const data = await res.json(); 35 | 36 | if (!validateData(data)) { 37 | console.error(`Invalid ${process.env.EXTERNAL_REQUESTS_URL} return data.`); 38 | return []; 39 | } 40 | 41 | return data; 42 | } 43 | 44 | /** 45 | * 46 | * @returns List of requests to ping from the environment variables. 47 | */ 48 | export function getEnvRequests(): PingRequest[] { 49 | if (!process.env.REQUESTS) return []; 50 | 51 | const data = JSON.parse(process.env.REQUESTS); 52 | 53 | if (!validateData(data)) { 54 | console.error("Invalid REQUESTS environment variable."); 55 | return []; 56 | } 57 | 58 | return data; 59 | } 60 | 61 | /** 62 | * 63 | * @param data any input source like fetch or env 64 | * @returns true if the data is a valid PingRequest array 65 | */ 66 | function validateData(data: any): data is PingRequest[] { 67 | return ( 68 | Array.isArray(data) && 69 | data.every((r) => { 70 | return ( 71 | typeof r === "object" && 72 | typeof r.url === "string" && 73 | typeof r.method === "string" && 74 | (typeof r.timeout === "number" || r.timeout === undefined) && 75 | (typeof r.prewarm === "boolean" || r.prewarm === undefined) && 76 | (typeof r.headers === "object" || r.headers === undefined) && 77 | (typeof r.body === "string" || r.body === undefined) 78 | ); 79 | }) 80 | ); 81 | } 82 | -------------------------------------------------------------------------------- /api/_ping.ts: -------------------------------------------------------------------------------- 1 | export type PingRequest = { 2 | url: string; 3 | method: string; 4 | body?: string; 5 | headers?: Record; 6 | timeout?: number; 7 | /** 8 | * Whether to prewarm your endpoint before timing the next request. 9 | * This is useful to avoid cold starts. 10 | */ 11 | prewarm?: boolean; 12 | }; 13 | 14 | export type PingResponse = { 15 | url: string; 16 | method: string; 17 | status?: number; 18 | latency?: number; 19 | body?: string; 20 | headers?: Record; 21 | error?: string; 22 | timestamp: number; 23 | region: string; 24 | }; 25 | 26 | export async function ping(request: PingRequest): Promise { 27 | const region = process.env.VERCEL_REGION || "unknown"; 28 | 29 | if (request.prewarm) { 30 | console.log(`Prewarming the request in '${region}'...`); 31 | await check(request); 32 | console.log(`Prewarming in '${region}' completed.`); 33 | await new Promise((resolve) => setTimeout(resolve, 1000)); // wait for 1s before firing the next request 34 | } 35 | 36 | try { 37 | // TODO: make it in a try/catch block instead? 38 | // REMINDER: we retry once if the request fails to make sure it's not a transient issue 39 | const res = await check(request).catch((e) => { 40 | console.error(`Request failed with ${e} in '${region}'. Retrying...`); 41 | return check(request); 42 | }); 43 | console.log(`Request succeded in '${region}'.`); 44 | 45 | return res; 46 | } catch (e) { 47 | const error = e instanceof Error ? e.message : String(e); 48 | console.error(`Request failed again with ${e} in '${region}'.`); 49 | 50 | return { 51 | error, 52 | url: request.url, 53 | method: request.method, 54 | timestamp: Date.now(), 55 | region, 56 | }; 57 | } 58 | } 59 | 60 | async function check(request: PingRequest): Promise { 61 | const region = process.env.VERCEL_REGION || "unknown"; 62 | const timeout = request.timeout || 30_000; // default 30s 63 | const controller = new AbortController(); 64 | 65 | const timeoutId = setTimeout( 66 | () => controller.abort(new Error(`Request timeout after ${timeout}ms.`)), 67 | timeout 68 | ); 69 | 70 | const start = Date.now(); 71 | const res = await fetch(request.url, { 72 | method: request.method, 73 | headers: { 74 | "User-Agent": "OpenStatus/1.0", 75 | ...request.headers, 76 | }, 77 | body: request.body, 78 | signal: controller.signal, 79 | }); 80 | const end = Date.now(); 81 | 82 | clearTimeout(timeoutId); 83 | 84 | const latency = end - start; 85 | const text = await res.text(); 86 | const headers = Object.fromEntries(res.headers.entries()); 87 | 88 | // NOTE: we limit the body to 1000 characters to avoid saving large payloads in tb 89 | const body = text.length > 1000 ? text.slice(0, 1000) + "..." : text; 90 | 91 | return { 92 | url: request.url, 93 | method: request.method, 94 | region, 95 | status: res.status, 96 | latency, 97 | body, 98 | headers, 99 | timestamp: start, 100 | }; 101 | } 102 | -------------------------------------------------------------------------------- /api/cron.ts: -------------------------------------------------------------------------------- 1 | import { waitUntil } from "@vercel/functions"; 2 | import type { PingResponse } from "./_ping"; 3 | import { regions } from "./_regions.js"; 4 | import { 5 | sendCampsiteMessage, 6 | sendDiscordMessage, 7 | sendSlackMessage, 8 | sendTelegramMessage, 9 | } from "./_notifications.js"; 10 | import { 11 | getEnvRequests, 12 | getExternalRequests, 13 | getFileRequests, 14 | } from "./_requests.js"; 15 | 16 | /** 17 | * REMINDER: VERCEL_URL can be available but requires the 18 | * _Project Settings -> Deployment Protection -> Vercel Authentificatio_ to be disabled(!) 19 | * We will use the VERCEL_PROJECT_PRODUCTION_URL instead to avoid this as it is the public URL. 20 | * Can be set manually to BASE_URL. 21 | */ 22 | 23 | const BASE_URL = 24 | process.env.BASE_URL || process.env.VERCEL_PROJECT_PRODUCTION_URL 25 | ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}` 26 | : "http://localhost:3000"; 27 | 28 | const FAILED_RATIO_THRESHOLD = 0.5; 29 | 30 | export async function GET(req: Request): Promise { 31 | const authHeader = req.headers.get("authorization"); 32 | if ( 33 | !process.env.CRON_SECRET || 34 | authHeader !== `Bearer ${process.env.CRON_SECRET}` 35 | ) { 36 | return new Response("Unauthorized", { status: 401 }); 37 | } 38 | 39 | const start = Date.now(); 40 | 41 | const allRequests = [ 42 | // file, 43 | ...getFileRequests(), 44 | // fetch 45 | ...(await getExternalRequests()), 46 | // env 47 | ...getEnvRequests(), 48 | ]; 49 | 50 | const fetchPromises = allRequests.flatMap((request) => { 51 | return regions.map(async (region) => { 52 | return fetch(`${BASE_URL}/api/edge/${region}`, { 53 | method: "POST", 54 | body: JSON.stringify(request), 55 | headers: { 56 | "Content-Type": "application/json", 57 | Authorization: `Bearer ${process.env.PING_SECRET}`, 58 | }, 59 | }); 60 | }); 61 | }); 62 | 63 | try { 64 | const res = await Promise.allSettled(fetchPromises); 65 | 66 | const map = new Map(); 67 | 68 | for (const result of res) { 69 | if (result.status === "rejected") { 70 | console.error(result.reason); 71 | } else if (result.status === "fulfilled") { 72 | try { 73 | console.log(result.value); 74 | const json = (await result.value.json()) as PingResponse; 75 | const key = `${json.method}:${json.url}`; 76 | const current = map.get(key) || { total: 0, ok: 0 }; 77 | 78 | // REMINDER: simple assertion by checking if the status code starts with 2xx or 3xx 79 | // TODO: improve the assertion for dynamic use cases 80 | const isOk = 81 | `${json.status}`.startsWith("2") || 82 | `${json.status}`.startsWith("3"); 83 | 84 | map.set(key, { 85 | total: current.total + 1, 86 | ok: current.ok + Number(isOk), 87 | }); 88 | } catch (error) { 89 | console.error("Error parsing JSON:", error); 90 | } 91 | } 92 | } 93 | 94 | Array.from(map.entries()).forEach(async ([key, value]) => { 95 | const ratio = value.ok / value.total; 96 | if (ratio > FAILED_RATIO_THRESHOLD) return; 97 | 98 | const message = `🚨 ${key} has ${value.ok}/${value.total} successful requests`; 99 | 100 | waitUntil(sendSlackMessage(message)); 101 | waitUntil(sendDiscordMessage(message)); 102 | waitUntil(sendCampsiteMessage(message)); 103 | waitUntil(sendTelegramMessage(message)); 104 | }); 105 | 106 | const end = Date.now(); 107 | 108 | return new Response(`${fetchPromises.length} requests in ${end - start}ms`); 109 | } catch (error) { 110 | console.error(error); 111 | 112 | return new Response("Internal Server Error", { status: 500 }); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /api/index.ts: -------------------------------------------------------------------------------- 1 | export const config = { 2 | runtime: "edge", 3 | }; 4 | 5 | const region = process.env.VERCEL_REGION || "unknown"; 6 | 7 | const META_DESCRIPTION = 8 | "Lightweight one-click solution to monitor your endpoints across multiple regions."; 9 | const META_TITLE = "OpenStatus Light | Vercel Edge Ping"; 10 | const META_URL = "https://light.openstatus.dev"; 11 | const META_OG_IMAGE = 12 | "https://www.openstatus.dev/api/og?title=Vercel%20Edge%20Ping&description=Lightweight%20one-click%20solution%20to%20monitor%20your%20endpoints%20across%20multiple%20regions.&footer=light.openstatus.dev"; 13 | 14 | export async function GET(): Promise { 15 | const text = ` 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |

${META_TITLE}

36 |

37 | Lightweight open-source one-click solution to monitor your endpoints across multiple regions. 38 |

39 |

40 | Your request has been executed in region ${region}. 41 |

42 |

By default, a cron job will run every day at 00:00 UTC to send a request to /api/cron and ping the following regions:

43 | 63 |

64 | Be notified via Slack, Discord, Campsite or Telegram if >50% of the regions are down. 65 |

66 |

More endpoints (with search params support):

67 |
    68 |
  • Get the latest requests by visiting /api/get.
  • 69 |
  • Get the latest stats by visiting /api/stats.
  • 70 |
  • Get the latest facets by visiting /api/facets.
  • 71 |
72 |

Once deployed, access your data by visiting logs.run/light and changing the base URL to your endpoint.

73 |

74 | Read more on GitHub 75 | · 76 | Build with Vercel and Tinybird 77 | · 78 | Powered by OpenStatus 79 |

80 | 81 | `; 82 | 83 | return new Response(text, { 84 | headers: { "Content-Type": "text/html; charset=utf-8" }, 85 | }); 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenStatus | Vercel Edge Ping 2 | 3 | No library. No UI. No maintenance. 4 | 5 | We want to provide you a lightweight version of [OpenStatus](https://openstatus.dev) to monitor your services. 6 | 7 | Therefore, we will be using Vercel's edge runtime to monitor your services across 18 regions as simple as possible. Read more about [vercel edge network regions](https://vercel.com/docs/edge-network/regions). 8 | 9 | Choose your [configuration](#configuration) and be ready in 5min to monitor your website or API services. 10 | 11 | You can even one-click self-host the service by adding the stringified array to the `REQUESTS` environment variables. (see [here](#environment-variables)) 12 | 13 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FopenstatusHQ%2Fvercel-edge-ping&env=CRON_SECRET,PING_SECRET) 14 | 15 | Currently supported [notification channels](#notification-channels) are: 16 | 17 | - Slack 18 | - Discord 19 | - Campsite 20 | - Telegram 21 | 22 | We also provide a 6 min. [YouTube](https://www.youtube.com/watch?v=cpurWC9Co1U) video for more visual content. If you have any trouble, feel free to open an issue, join our [Discord](https://openstatus.dev/discord) or message us to [ping@openstatus.dev](mailto:ping@openstatus.dev) 23 | 24 | If storing the data to [Tinybird](https://www.tinybird.co), you can use the [OpenStatus Light Viewer](https://data-table.openstatus.dev/light) to filter and learn from your pings. 25 | 26 | ## Getting Started 27 | 28 | To work/test it locally: 29 | 30 | ```bash 31 | pnpm install 32 | pnpm start 33 | ``` 34 | 35 | ### Vercel CLI 36 | 37 | Make sure to have the [Vercel CLI](https://vercel.com/docs/cli) running on your machine. When you first start the project, you will get asked to connect it to your vercel account. 38 | 39 | Checkout `.env.example` for the (required) environment variables. Use the Vercel CLI and the [`add env`](https://vercel.com/docs/cli/env) command: 40 | 41 | ```bash 42 | vercel env add 43 | ``` 44 | 45 | ### Tinybird CLI (optional) 46 | 47 | If you want to ingest the data and keep track of the response times, add the `TINYBIRD_TOKEN` to your environment variables. 48 | 49 | Include the [Tinybird CLI](https://www.tinybird.co/docs/cli) as well to easily set the pipe and datasource to ingest and get the data: 50 | 51 | ```bash 52 | python3 -m venv .venv 53 | source .venv/bin/activate 54 | pip install tinybird-cli 55 | tb auth -i 56 | ``` 57 | 58 | Add `--dry-run` to the commands if you want to first test them: 59 | 60 | ```bash 61 | tb push tb/datasources/http_ping_responses.datasource 62 | tb push tb/pipes/endpoint__get_http.pipe 63 | tb push tb/pipes/endpoint__get_http_stats.pipe 64 | tb push tb/pipes/endpoint__get_http_facets.pipe 65 | ``` 66 | 67 | #### API endpoint 68 | 69 | If you've connected your database to Tinybird, we provide you a some simple `GET` endpoint to query your pings. 70 | 71 | The `/api/get` endpoint (`endpoint__get_http.pipe`) accepts the following query parameters: 72 | 73 | | **Parameter** | **Type** | **Description** | 74 | | ---------------- | -------- | ----------------------------------------------------- | 75 | | `pageIndex` | `number` | The page number for pagination (starts at 0) | 76 | | `pageSize` | `number` | Number of results per page (defaults to 100) | 77 | | `orderBy` | `string` | Column to sort by (defaults to 'timestamp') | 78 | | `orderDir` | `string` | Sort direction - 'ASC' or 'DESC' (defaults to 'DESC') | 79 | | `latencyStart` | `number` | Filter results with latency >= this value (ms) | 80 | | `latencyEnd` | `number` | Filter results with latency <= this value (ms) | 81 | | `statuses` | `string` | Filter by HTTP status codes (comma-separated list) | 82 | | `regions` | `string` | Filter by edge regions (comma-separated list) | 83 | | `methods` | `string` | Filter by HTTP methods (comma-separated list) | 84 | | `url` | `string` | Filter URLs containing this string | 85 | | `timestampStart` | `number` | Unix timestamp in ms (defaults to 30 days prior) | 86 | | `timestampEnd` | `number` | Unix timestamp in ms (defaults to now) | 87 | 88 | Moreover, to make best use of the [OpenStatus Light Viewer](https://data-table.openstatus.dev/light), we support two more API endpoints. They both extend the above query params. 89 | 90 | - `/api/stats` endpoint (`endpoint__get_http_stats.pipe`) for the chart values (incl. `interval` param) 91 | 92 | | **Parameter** | **Type** | **Description** | 93 | | ------------- | -------- | ----------------------------------------------------------------------------------- | 94 | | `interval` | `number` | Interval of grouped data in minutes (defaults to 1_440 minutes equivalent to 1 day) | 95 | 96 | - `/api/facets` endpoint (`endpoint__get_http_facets.pipe`) for the table facets (no additional param) 97 | 98 | All endpoints are just a layer to access the tinybird pipe responses. They share the following response object example: 99 | 100 | ```json 101 | { 102 | "meta": [], 103 | "data": [], 104 | "rows": 20, 105 | "rows_before_limit_at_least": 100, 106 | "statistics": { 107 | "elapsed": 0.004015279, 108 | "rows_read": 2845, 109 | "bytes_read": 725311 110 | } 111 | } 112 | ``` 113 | 114 | > [!NOTE] 115 | > The `/api/get`, `/api/stats`, `/api/facets` endpoints will be accessible by anyone if you are not securing it yourself. 116 | 117 | ## Configuration 118 | 119 | ### Monitors 120 | 121 | A `PingRequest` includes the below props: 122 | 123 | | **Property** | **Type** | **Description** | 124 | | ------------ | ------------------------ | ----------------------------------------------------------------------- | 125 | | `url` | `string` | The URL to send the ping request to. | 126 | | `method` | `string` | The HTTP method to use for the request (e.g., GET, POST). | 127 | | `body?` | `string` | Optional request body. | 128 | | `headers?` | `Record` | Optional headers to include in the request. | 129 | | `timeout?` | `number` | Optional timeout in milliseconds for the request. Defaults to 50_000ms. | 130 | | `prewarm?` | `boolean` | Optional flag to prewarm the endpoint before timing the next request. | 131 | 132 | There are multiple ways to add your monitors: 133 | 134 | - via `./api/resources.json` file _but that would require a fork + changes_ 135 | - via a fetch call using the `REQUEST_GET_URL` returning a type of `PingRequest[]` _but that would require you to maintain that connection_ 136 | - via `.env` where we stringify the `PingRequest[]` array and read it out 137 | 138 | All three options can work parallely. 139 | 140 | We _roughly_ validate the external input. If they don't match the expected type, you'll see a `console.error` in your logs. 141 | 142 | #### Environment variables 143 | 144 | The **fastest way to get started** without having to commit any code changes is to add the stringified list to your `REQUESTS` environment variables. 145 | 146 | For example: 147 | 148 | ``` 149 | [{"url":"https://openstat.us/200","method":"GET", "prewarm":true}] 150 | ``` 151 | 152 | > [!NOTE] 153 | > Whenever you change the environment variable, you'll need to rebuild/redeploy the app to included the latest changes. 154 | 155 | #### File reading 156 | 157 | Add your endpoints statically to the list `./api/resources.json` file. 158 | 159 | For example: 160 | 161 | ```json 162 | [{ "url": "https://openstat.us/200", "method": "GET", "prewarm": true }] 163 | ``` 164 | 165 | #### Fetching resources 166 | 167 | Create an endpoint that returns the list. Use the `EXTERNAL_REQUESTS_URL` to fetch the list dynamically on every ping. 168 | 169 | To secure your endpoint, we provide the `EXTERNAL_REQUESTS_SECRET` environment variable that gets passed as property to the header `Authorization: Bearer EXTERNAL_REQUESTS_SECRET`. 170 | 171 | ### vercel.json 172 | 173 | We have made some configurations within `vercel.json`. Let's break them down. 174 | 175 | The [maximum duration](https://vercel.com/docs/functions/configuring-functions/duration) of the serverless functions are set to the max of the _free plan_: 176 | 177 | ``` 178 | "functions": { 179 | "api/cron.ts": { 180 | "maxDuration": 60 181 | } 182 | } 183 | ``` 184 | 185 | The [cron jobs](https://vercel.com/docs/cron-jobs) are set to the maximum of the _free plan_ which is daily: 186 | 187 | ``` 188 | "crons": [ 189 | { 190 | "path": "/api/cron", 191 | "schedule": "0 0 * * *" 192 | } 193 | ] 194 | ``` 195 | 196 | If you are on a _pro plan_, update it to the cron expression you'd like to use. 197 | 198 | The cron endpoint is automatically secured by including the [`CRON_SECRET`](https://vercel.com/docs/cron-jobs/manage-cron-jobs#securing-cron-jobs) environment variable. 199 | 200 | ### GitHub Workflows (optional) 201 | 202 | Optionally, if you want to keep the vercel _free plan_ and increase the periodicity of the cron job, you can work it out by using github actions. 203 | 204 | Go to your _GitHub repository → Settings → Secrets and variables → Actions → New repository secret_ and add: 205 | 206 | - `CRON_SECRET` - the same one as in vercel envs 207 | - `BASE_URL` - the production URL from vercel 208 | 209 | You can either trigger it manually via `workflow_dispatch` or uncomment and update the `schedule.cron` to the cron expression you'd like to periodically run the attached curl. 210 | 211 | ## Notification Channels 212 | 213 | If set, we will send a message if >50% of the regions of a specific endpoint are failing. An endpoint fails, if the response status code **doesn't start with `2` or `3`**. 214 | 215 | Notifications to the different services will be send only if the environment variables are set. 216 | 217 | ### Slack Webhook (optional) 218 | 219 | If you want to get notified whenever an endpoint is not healthy, add the `SLACK_WEBHOOK_URL` to your environment variables. 220 | 221 | To create a webhook for a specific channel you'd like to post the messages to, [follow the guide](https://api.slack.com/messaging/webhooks). 222 | 223 | ### Discord Webhook (optional) 224 | 225 | If you want to get notified whenever an endpoint is not healthy, add the `DISCORD_WEBHOOK_URL` to your environment variables. 226 | 227 | To create a webhook for a specific channel you'd like to post the messages to, [follow the guide](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks). 228 | 229 | ### Campsite Post (optional) 230 | 231 | If you want to get notified whenever an endpoint is not healthy, add the `CAMPSITE_API_KEY` and `CAMPSITE_CHANNEL_ID` to your environment variables. 232 | 233 | To create an API key, [follow the docs](https://developers.campsite.com/api-reference/introduction). You will need to connect your integration to a channel and copy the channel id as well. 234 | 235 | ### Telegram Bot (optional) 236 | 237 | If you want to get notified whenever an endpoint is not healthy, add the `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` to your environment variables. 238 | 239 | To create a telegram bot, [follow the gist](https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a#how-to-get-telegram-bot-chat-id). 240 | 241 | ## Deployment 242 | 243 | Check the Vercel CLI docs regarding [`deploy`](https://vercel.com/docs/cli/deploy) commands if you want to learn more. Otherwise: 244 | 245 | ```bash 246 | # deploy to preview 247 | vercel 248 | # deploy to production 249 | vercel --prod 250 | ``` 251 | 252 | ## More 253 | 254 | > [!NOTE] 255 | > If you host your services on Vercel and want to make sure the provider is up, this is a bad idea as the edge ping depends on Vercel itself. Instead, it is good to keep uptime of your own services like hosted APIs, getting latency over time, or be informed whenever your services are not responding as expected. 256 | 257 | If you are on a pro plan on vercel, you are allowed for _Unlimited cron invocations_ instead of _Triggered once a day_. Fork and change the `vercel.json` content to whatevery cron you'd like to. Use [crontab.guru](https://crontab.guru) to quickly edit and validate the cron expression. 258 | 259 | Test the notifications with [openstat.us](https://openstat.us) where you can define the returned status code with ease. 260 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@vercel/functions': 12 | specifier: ^1.5.0 13 | version: 1.5.0 14 | devDependencies: 15 | '@types/node': 16 | specifier: ^22.9.0 17 | version: 22.9.0 18 | typescript: 19 | specifier: ^5.6.3 20 | version: 5.6.3 21 | vercel: 22 | specifier: ^32.4.1 23 | version: 32.7.2 24 | 25 | packages: 26 | 27 | '@cspotcode/source-map-support@0.8.1': 28 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 29 | engines: {node: '>=12'} 30 | 31 | '@edge-runtime/cookies@3.4.1': 32 | resolution: {integrity: sha512-z27BvgPxI73CgSlxU/NAUf1Q/shnqi6cobHEowf6VuLdSjGR3NjI2Y5dZUIBbK2zOJVZbXcHsVzJjz8LklteFQ==} 33 | engines: {node: '>=16'} 34 | 35 | '@edge-runtime/format@2.2.0': 36 | resolution: {integrity: sha512-gPrS6AVw/qJJL0vcxMXv4kFXCU3ZTCD1uuJpwX15YxHV8BgU9OG5v9LrkkXcr96PBT/9epypfNJMhlWADuEziw==} 37 | engines: {node: '>=16'} 38 | 39 | '@edge-runtime/node-utils@2.2.1': 40 | resolution: {integrity: sha512-RUl/439BHKshkhSGFRlZ1kzy68wL4mn8VNKDSZr3p0tciyZ33Mjfpl+vofqnHqXRmDI6nLnZpfJvhY3D88o0pA==} 41 | engines: {node: '>=16'} 42 | 43 | '@edge-runtime/ponyfill@2.4.1': 44 | resolution: {integrity: sha512-ZbR/EViY3gg2rmEAQTKPa6mXl4aR1/+cFcQe4r1segCjEbTAxT6PWu40odbu/KlZKSysEb2O/BWIC2lJgSJOMQ==} 45 | engines: {node: '>=16'} 46 | 47 | '@edge-runtime/primitives@4.0.5': 48 | resolution: {integrity: sha512-t7QiN5d/KpXgCvIfSt6Nm9Hj3WVdNgc5CpOD73jasY+9EvTI7Ngdj5cXvjcHrPcmYWJZMySPgeEeoL/1N/Llag==} 49 | engines: {node: '>=16'} 50 | 51 | '@edge-runtime/vm@3.1.7': 52 | resolution: {integrity: sha512-hUMFbDQ/nZN+1TLMi6iMO1QFz9RSV8yGG8S42WFPFma1d7VSNE0eMdJUmwjmtav22/iQkzHMmu6oTSfAvRGS8g==} 53 | engines: {node: '>=16'} 54 | 55 | '@fastify/busboy@2.1.1': 56 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 57 | engines: {node: '>=14'} 58 | 59 | '@jridgewell/resolve-uri@3.1.2': 60 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 61 | engines: {node: '>=6.0.0'} 62 | 63 | '@jridgewell/sourcemap-codec@1.5.0': 64 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 65 | 66 | '@jridgewell/trace-mapping@0.3.9': 67 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 68 | 69 | '@mapbox/node-pre-gyp@1.0.11': 70 | resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} 71 | hasBin: true 72 | 73 | '@nodelib/fs.scandir@2.1.5': 74 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 75 | engines: {node: '>= 8'} 76 | 77 | '@nodelib/fs.stat@2.0.5': 78 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 79 | engines: {node: '>= 8'} 80 | 81 | '@nodelib/fs.walk@1.2.8': 82 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 83 | engines: {node: '>= 8'} 84 | 85 | '@rollup/pluginutils@4.2.1': 86 | resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} 87 | engines: {node: '>= 8.0.0'} 88 | 89 | '@sinclair/typebox@0.25.24': 90 | resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==} 91 | 92 | '@tootallnate/once@2.0.0': 93 | resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} 94 | engines: {node: '>= 10'} 95 | 96 | '@ts-morph/common@0.11.1': 97 | resolution: {integrity: sha512-7hWZS0NRpEsNV8vWJzg7FEz6V8MaLNeJOmwmghqUXTpzk16V1LLZhdo+4QvE/+zv4cVci0OviuJFnqhEfoV3+g==} 98 | 99 | '@tsconfig/node10@1.0.11': 100 | resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} 101 | 102 | '@tsconfig/node12@1.0.11': 103 | resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} 104 | 105 | '@tsconfig/node14@1.0.3': 106 | resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} 107 | 108 | '@tsconfig/node16@1.0.4': 109 | resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} 110 | 111 | '@types/json-schema@7.0.15': 112 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 113 | 114 | '@types/node@14.18.33': 115 | resolution: {integrity: sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==} 116 | 117 | '@types/node@22.9.0': 118 | resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==} 119 | 120 | '@vercel/build-utils@7.3.0': 121 | resolution: {integrity: sha512-RJwqrGYSk75auHZqWmlSL+a5JsWv+4SF1AxNQJ+KpF3XWZ/8yThkN/jHBfNxMmW6VvNczSVtMaXI0/2Sess6Eg==} 122 | 123 | '@vercel/error-utils@2.0.2': 124 | resolution: {integrity: sha512-Sj0LFafGpYr6pfCqrQ82X6ukRl5qpmVrHM/191kNYFqkkB9YkjlMAj6QcEsvCG259x4QZ7Tya++0AB85NDPbKQ==} 125 | 126 | '@vercel/fun@1.1.0': 127 | resolution: {integrity: sha512-SpuPAo+MlAYMtcMcC0plx7Tv4Mp7SQhJJj1iIENlOnABL24kxHpL09XLQMGzZIzIW7upR8c3edwgfpRtp+dhVw==} 128 | engines: {node: '>= 10'} 129 | 130 | '@vercel/functions@1.5.0': 131 | resolution: {integrity: sha512-ub3ptVeOsx8UPgiTv9+rpQJqmF7VG8QIzguBZo0E0VRAyJliB8bt1ooB9Wrh3333dKzMNS8NMe3iFtf6OPUP3A==} 132 | engines: {node: '>= 16'} 133 | peerDependencies: 134 | '@aws-sdk/credential-provider-web-identity': '*' 135 | peerDependenciesMeta: 136 | '@aws-sdk/credential-provider-web-identity': 137 | optional: true 138 | 139 | '@vercel/gatsby-plugin-vercel-analytics@1.0.11': 140 | resolution: {integrity: sha512-iTEA0vY6RBPuEzkwUTVzSHDATo1aF6bdLLspI68mQ/BTbi5UQEGjpjyzdKOVcSYApDtFU6M6vypZ1t4vIEnHvw==} 141 | 142 | '@vercel/gatsby-plugin-vercel-builder@2.0.12': 143 | resolution: {integrity: sha512-S1RkywrUItewqg06T3L4cgYfiwi2BFngHIIerhOYhVuD9A+yfMgxnH5dkbu6nujmV1SEws+Q92wSiPfLPmO0eA==} 144 | 145 | '@vercel/go@3.0.4': 146 | resolution: {integrity: sha512-hMIJm2xwU1HT56YRNF8HNOnIFNH7WnGl1l2D6lc6UJk7XdCCh1Dm0nsqLqki2SprTUh3I+53pTQaqgRsFGf06A==} 147 | 148 | '@vercel/hydrogen@1.0.1': 149 | resolution: {integrity: sha512-4PYk4LeIWPTjGtgnxvB0Hdw7aqCau843/96K2xX3z9pa0Hn//pUnZBMz2jrs5MRseCm1Li1LdQAK3u8/vaUnVQ==} 150 | 151 | '@vercel/next@4.0.15': 152 | resolution: {integrity: sha512-BxMxIJrya7MS6IWrQIaQaYHPmq7WoZFLX909RBpNoAG5wgzrTrW756d2EsibBwGo7sQYBv2atyI5GqBIHzYbWg==} 153 | 154 | '@vercel/nft@0.24.2': 155 | resolution: {integrity: sha512-KhY3Ky/lCqE+fHpOXiKOLnXYJ49PZh1dyDSfVtZhmYtmica0NQgyO6kPOAGDNWqD9IOBx8hb65upxxjfnfa1JA==} 156 | engines: {node: '>=16'} 157 | hasBin: true 158 | 159 | '@vercel/node@3.0.12': 160 | resolution: {integrity: sha512-OiNHiUe1LX/CfDrQ07ntPsoYhJiC38mEeErYeqA6YNVAz3QGdX3pthiaIig2KPqeeYkEx5bSkVIqQtQOTJBuLQ==} 161 | 162 | '@vercel/python@4.1.0': 163 | resolution: {integrity: sha512-EIQXK5zL6fce0Barh74gc7xyLtRyvgmLZDIVQ8yJLtFxPlPCRY3GXkdJ7Jdcw8Pd0uuVF0vIHatv18xSLbcwtg==} 164 | 165 | '@vercel/redwood@2.0.5': 166 | resolution: {integrity: sha512-9iWTxfMkC7yNnwN2xxOdptiIDAgXe1V1fh3aw92MWt5PBRcFY9RqgIPF7Q3Qa7yzQFgpbHwCnSTqWO+HCEuFtw==} 167 | 168 | '@vercel/remix-builder@2.0.14': 169 | resolution: {integrity: sha512-c+ILERSRq404sf6kt0qWhYhuxWkkoTEm2FdLoUnVs21K6kzGtJMJbUExEHoPZvN9a0tq86ZU86jVvRZV6WL0cQ==} 170 | 171 | '@vercel/routing-utils@3.1.0': 172 | resolution: {integrity: sha512-Ci5xTjVTJY/JLZXpCXpLehMft97i9fH34nu9PGav6DtwkVUF6TOPX86U0W0niQjMZ5n6/ZP0BwcJK2LOozKaGw==} 173 | 174 | '@vercel/ruby@2.0.4': 175 | resolution: {integrity: sha512-EpZyfF6wFGzFDmubFIh/EZtYpKindmXx/69xSfKEBTVU0afgljyOOICbyZePe5tvigfOEBLSLgrt/2nN+MlLtA==} 176 | 177 | '@vercel/static-build@2.0.14': 178 | resolution: {integrity: sha512-l5eQtJbk5Pc+P8XARDnpcbX4LnK3bGy7uf6S1aFOD4h6F8iBdg0agWTufZnq5BI91pcPVICPazM5BYhigIEznQ==} 179 | 180 | '@vercel/static-config@3.0.0': 181 | resolution: {integrity: sha512-2qtvcBJ1bGY0dYGYh3iM7yGKkk971FujLEDXzuW5wcZsPr1GSEjO/w2iSr3qve6nDDtBImsGoDEnus5FI4+fIw==} 182 | 183 | abbrev@1.1.1: 184 | resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} 185 | 186 | acorn-walk@8.3.4: 187 | resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} 188 | engines: {node: '>=0.4.0'} 189 | 190 | acorn@8.14.0: 191 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} 192 | engines: {node: '>=0.4.0'} 193 | hasBin: true 194 | 195 | agent-base@6.0.2: 196 | resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} 197 | engines: {node: '>= 6.0.0'} 198 | 199 | ajv@6.12.6: 200 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 201 | 202 | ajv@8.6.3: 203 | resolution: {integrity: sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==} 204 | 205 | ansi-regex@5.0.1: 206 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 207 | engines: {node: '>=8'} 208 | 209 | any-promise@1.3.0: 210 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 211 | 212 | anymatch@3.1.3: 213 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 214 | engines: {node: '>= 8'} 215 | 216 | aproba@2.0.0: 217 | resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} 218 | 219 | are-we-there-yet@2.0.0: 220 | resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} 221 | engines: {node: '>=10'} 222 | deprecated: This package is no longer supported. 223 | 224 | arg@4.1.0: 225 | resolution: {integrity: sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==} 226 | 227 | arg@4.1.3: 228 | resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} 229 | 230 | async-listen@1.2.0: 231 | resolution: {integrity: sha512-CcEtRh/oc9Jc4uWeUwdpG/+Mb2YUHKmdaTf0gUr7Wa+bfp4xx70HOb3RuSTJMvqKNB1TkdTfjLdrcz2X4rkkZA==} 232 | 233 | async-listen@3.0.0: 234 | resolution: {integrity: sha512-V+SsTpDqkrWTimiotsyl33ePSjA5/KrithwupuvJ6ztsqPvGv6ge4OredFhPffVXiLN/QUWvE0XcqJaYgt6fOg==} 235 | engines: {node: '>= 14'} 236 | 237 | async-listen@3.0.1: 238 | resolution: {integrity: sha512-cWMaNwUJnf37C/S5TfCkk/15MwbPRwVYALA2jtjkbHjCmAPiDXyNJy2q3p1KAZzDLHAWyarUWSujUoHR4pEgrA==} 239 | engines: {node: '>= 14'} 240 | 241 | async-sema@3.1.1: 242 | resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} 243 | 244 | balanced-match@1.0.2: 245 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 246 | 247 | binary-extensions@2.3.0: 248 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 249 | engines: {node: '>=8'} 250 | 251 | bindings@1.5.0: 252 | resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} 253 | 254 | brace-expansion@1.1.11: 255 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 256 | 257 | braces@3.0.3: 258 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 259 | engines: {node: '>=8'} 260 | 261 | buffer-crc32@0.2.13: 262 | resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} 263 | 264 | bytes@3.1.0: 265 | resolution: {integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==} 266 | engines: {node: '>= 0.8'} 267 | 268 | chokidar@3.3.1: 269 | resolution: {integrity: sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==} 270 | engines: {node: '>= 8.10.0'} 271 | 272 | chownr@1.1.4: 273 | resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} 274 | 275 | chownr@2.0.0: 276 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} 277 | engines: {node: '>=10'} 278 | 279 | code-block-writer@10.1.1: 280 | resolution: {integrity: sha512-67ueh2IRGst/51p0n6FvPrnRjAGHY5F8xdjkgrYE7DDzpJe6qA07RYQ9VcoUeo5ATOjSOiWpSL3SWBRRbempMw==} 281 | 282 | color-support@1.1.3: 283 | resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} 284 | hasBin: true 285 | 286 | concat-map@0.0.1: 287 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 288 | 289 | console-control-strings@1.1.0: 290 | resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} 291 | 292 | content-type@1.0.4: 293 | resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==} 294 | engines: {node: '>= 0.6'} 295 | 296 | convert-hrtime@3.0.0: 297 | resolution: {integrity: sha512-7V+KqSvMiHp8yWDuwfww06XleMWVVB9b9tURBx+G7UTADuo5hYPuowKloz4OzOqbPezxgo+fdQ1522WzPG4OeA==} 298 | engines: {node: '>=8'} 299 | 300 | create-require@1.1.1: 301 | resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} 302 | 303 | cross-spawn@7.0.5: 304 | resolution: {integrity: sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==} 305 | engines: {node: '>= 8'} 306 | 307 | debug@4.1.1: 308 | resolution: {integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==} 309 | deprecated: Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797) 310 | peerDependencies: 311 | supports-color: '*' 312 | peerDependenciesMeta: 313 | supports-color: 314 | optional: true 315 | 316 | debug@4.3.7: 317 | resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} 318 | engines: {node: '>=6.0'} 319 | peerDependencies: 320 | supports-color: '*' 321 | peerDependenciesMeta: 322 | supports-color: 323 | optional: true 324 | 325 | delegates@1.0.0: 326 | resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} 327 | 328 | depd@1.1.2: 329 | resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} 330 | engines: {node: '>= 0.6'} 331 | 332 | detect-libc@2.0.3: 333 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 334 | engines: {node: '>=8'} 335 | 336 | diff@4.0.2: 337 | resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} 338 | engines: {node: '>=0.3.1'} 339 | 340 | edge-runtime@2.5.7: 341 | resolution: {integrity: sha512-gA4qSVP0sNwJlkdQ2nahDPASlSl8twUd17o+JolPa1EtXpLTGzIpOETvodgJwXIxa+zaD8bnAXCdsWrx2PhlVQ==} 342 | engines: {node: '>=16'} 343 | hasBin: true 344 | 345 | emoji-regex@8.0.0: 346 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 347 | 348 | end-of-stream@1.1.0: 349 | resolution: {integrity: sha512-EoulkdKF/1xa92q25PbjuDcgJ9RDHYU2Rs3SCIvs2/dSQ3BpmxneNHmA/M7fe60M3PrV7nNGTTNbkK62l6vXiQ==} 350 | 351 | end-of-stream@1.4.4: 352 | resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} 353 | 354 | esbuild-android-64@0.14.47: 355 | resolution: {integrity: sha512-R13Bd9+tqLVFndncMHssZrPWe6/0Kpv2/dt4aA69soX4PRxlzsVpCvoJeFE8sOEoeVEiBkI0myjlkDodXlHa0g==} 356 | engines: {node: '>=12'} 357 | cpu: [x64] 358 | os: [android] 359 | 360 | esbuild-android-arm64@0.14.47: 361 | resolution: {integrity: sha512-OkwOjj7ts4lBp/TL6hdd8HftIzOy/pdtbrNA4+0oVWgGG64HrdVzAF5gxtJufAPOsEjkyh1oIYvKAUinKKQRSQ==} 362 | engines: {node: '>=12'} 363 | cpu: [arm64] 364 | os: [android] 365 | 366 | esbuild-darwin-64@0.14.47: 367 | resolution: {integrity: sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA==} 368 | engines: {node: '>=12'} 369 | cpu: [x64] 370 | os: [darwin] 371 | 372 | esbuild-darwin-arm64@0.14.47: 373 | resolution: {integrity: sha512-seCmearlQyvdvM/noz1L9+qblC5vcBrhUaOoLEDDoLInF/VQ9IkobGiLlyTPYP5dW1YD4LXhtBgOyevoIHGGnw==} 374 | engines: {node: '>=12'} 375 | cpu: [arm64] 376 | os: [darwin] 377 | 378 | esbuild-freebsd-64@0.14.47: 379 | resolution: {integrity: sha512-ZH8K2Q8/Ux5kXXvQMDsJcxvkIwut69KVrYQhza/ptkW50DC089bCVrJZZ3sKzIoOx+YPTrmsZvqeZERjyYrlvQ==} 380 | engines: {node: '>=12'} 381 | cpu: [x64] 382 | os: [freebsd] 383 | 384 | esbuild-freebsd-arm64@0.14.47: 385 | resolution: {integrity: sha512-ZJMQAJQsIOhn3XTm7MPQfCzEu5b9STNC+s90zMWe2afy9EwnHV7Ov7ohEMv2lyWlc2pjqLW8QJnz2r0KZmeAEQ==} 386 | engines: {node: '>=12'} 387 | cpu: [arm64] 388 | os: [freebsd] 389 | 390 | esbuild-linux-32@0.14.47: 391 | resolution: {integrity: sha512-FxZOCKoEDPRYvq300lsWCTv1kcHgiiZfNrPtEhFAiqD7QZaXrad8LxyJ8fXGcWzIFzRiYZVtB3ttvITBvAFhKw==} 392 | engines: {node: '>=12'} 393 | cpu: [ia32] 394 | os: [linux] 395 | 396 | esbuild-linux-64@0.14.47: 397 | resolution: {integrity: sha512-nFNOk9vWVfvWYF9YNYksZptgQAdstnDCMtR6m42l5Wfugbzu11VpMCY9XrD4yFxvPo9zmzcoUL/88y0lfJZJJw==} 398 | engines: {node: '>=12'} 399 | cpu: [x64] 400 | os: [linux] 401 | 402 | esbuild-linux-arm64@0.14.47: 403 | resolution: {integrity: sha512-ywfme6HVrhWcevzmsufjd4iT3PxTfCX9HOdxA7Hd+/ZM23Y9nXeb+vG6AyA6jgq/JovkcqRHcL9XwRNpWG6XRw==} 404 | engines: {node: '>=12'} 405 | cpu: [arm64] 406 | os: [linux] 407 | 408 | esbuild-linux-arm@0.14.47: 409 | resolution: {integrity: sha512-ZGE1Bqg/gPRXrBpgpvH81tQHpiaGxa8c9Rx/XOylkIl2ypLuOcawXEAo8ls+5DFCcRGt/o3sV+PzpAFZobOsmA==} 410 | engines: {node: '>=12'} 411 | cpu: [arm] 412 | os: [linux] 413 | 414 | esbuild-linux-mips64le@0.14.47: 415 | resolution: {integrity: sha512-mg3D8YndZ1LvUiEdDYR3OsmeyAew4MA/dvaEJxvyygahWmpv1SlEEnhEZlhPokjsUMfRagzsEF/d/2XF+kTQGg==} 416 | engines: {node: '>=12'} 417 | cpu: [mips64el] 418 | os: [linux] 419 | 420 | esbuild-linux-ppc64le@0.14.47: 421 | resolution: {integrity: sha512-WER+f3+szmnZiWoK6AsrTKGoJoErG2LlauSmk73LEZFQ/iWC+KhhDsOkn1xBUpzXWsxN9THmQFltLoaFEH8F8w==} 422 | engines: {node: '>=12'} 423 | cpu: [ppc64] 424 | os: [linux] 425 | 426 | esbuild-linux-riscv64@0.14.47: 427 | resolution: {integrity: sha512-1fI6bP3A3rvI9BsaaXbMoaOjLE3lVkJtLxsgLHqlBhLlBVY7UqffWBvkrX/9zfPhhVMd9ZRFiaqXnB1T7BsL2g==} 428 | engines: {node: '>=12'} 429 | cpu: [riscv64] 430 | os: [linux] 431 | 432 | esbuild-linux-s390x@0.14.47: 433 | resolution: {integrity: sha512-eZrWzy0xFAhki1CWRGnhsHVz7IlSKX6yT2tj2Eg8lhAwlRE5E96Hsb0M1mPSE1dHGpt1QVwwVivXIAacF/G6mw==} 434 | engines: {node: '>=12'} 435 | cpu: [s390x] 436 | os: [linux] 437 | 438 | esbuild-netbsd-64@0.14.47: 439 | resolution: {integrity: sha512-Qjdjr+KQQVH5Q2Q1r6HBYswFTToPpss3gqCiSw2Fpq/ua8+eXSQyAMG+UvULPqXceOwpnPo4smyZyHdlkcPppQ==} 440 | engines: {node: '>=12'} 441 | cpu: [x64] 442 | os: [netbsd] 443 | 444 | esbuild-openbsd-64@0.14.47: 445 | resolution: {integrity: sha512-QpgN8ofL7B9z8g5zZqJE+eFvD1LehRlxr25PBkjyyasakm4599iroUpaj96rdqRlO2ShuyqwJdr+oNqWwTUmQw==} 446 | engines: {node: '>=12'} 447 | cpu: [x64] 448 | os: [openbsd] 449 | 450 | esbuild-sunos-64@0.14.47: 451 | resolution: {integrity: sha512-uOeSgLUwukLioAJOiGYm3kNl+1wJjgJA8R671GYgcPgCx7QR73zfvYqXFFcIO93/nBdIbt5hd8RItqbbf3HtAQ==} 452 | engines: {node: '>=12'} 453 | cpu: [x64] 454 | os: [sunos] 455 | 456 | esbuild-windows-32@0.14.47: 457 | resolution: {integrity: sha512-H0fWsLTp2WBfKLBgwYT4OTfFly4Im/8B5f3ojDv1Kx//kiubVY0IQunP2Koc/fr/0wI7hj3IiBDbSrmKlrNgLQ==} 458 | engines: {node: '>=12'} 459 | cpu: [ia32] 460 | os: [win32] 461 | 462 | esbuild-windows-64@0.14.47: 463 | resolution: {integrity: sha512-/Pk5jIEH34T68r8PweKRi77W49KwanZ8X6lr3vDAtOlH5EumPE4pBHqkCUdELanvsT14yMXLQ/C/8XPi1pAtkQ==} 464 | engines: {node: '>=12'} 465 | cpu: [x64] 466 | os: [win32] 467 | 468 | esbuild-windows-arm64@0.14.47: 469 | resolution: {integrity: sha512-HFSW2lnp62fl86/qPQlqw6asIwCnEsEoNIL1h2uVMgakddf+vUuMcCbtUY1i8sst7KkgHrVKCJQB33YhhOweCQ==} 470 | engines: {node: '>=12'} 471 | cpu: [arm64] 472 | os: [win32] 473 | 474 | esbuild@0.14.47: 475 | resolution: {integrity: sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA==} 476 | engines: {node: '>=12'} 477 | hasBin: true 478 | 479 | estree-walker@2.0.2: 480 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 481 | 482 | etag@1.8.1: 483 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} 484 | engines: {node: '>= 0.6'} 485 | 486 | events-intercept@2.0.0: 487 | resolution: {integrity: sha512-blk1va0zol9QOrdZt0rFXo5KMkNPVSp92Eju/Qz8THwKWKRKeE0T8Br/1aW6+Edkyq9xHYgYxn2QtOnUKPUp+Q==} 488 | 489 | execa@3.2.0: 490 | resolution: {integrity: sha512-kJJfVbI/lZE1PZYDI5VPxp8zXPO9rtxOkhpZ0jMKha56AI9y2gGVC6bkukStQf0ka5Rh15BA5m7cCCH4jmHqkw==} 491 | engines: {node: ^8.12.0 || >=9.7.0} 492 | 493 | exit-hook@2.2.1: 494 | resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} 495 | engines: {node: '>=6'} 496 | 497 | fast-deep-equal@3.1.3: 498 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 499 | 500 | fast-glob@3.3.2: 501 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} 502 | engines: {node: '>=8.6.0'} 503 | 504 | fast-json-stable-stringify@2.1.0: 505 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 506 | 507 | fastq@1.17.1: 508 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 509 | 510 | fd-slicer@1.1.0: 511 | resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} 512 | 513 | file-uri-to-path@1.0.0: 514 | resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} 515 | 516 | fill-range@7.1.1: 517 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 518 | engines: {node: '>=8'} 519 | 520 | fs-extra@11.1.0: 521 | resolution: {integrity: sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==} 522 | engines: {node: '>=14.14'} 523 | 524 | fs-extra@8.1.0: 525 | resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} 526 | engines: {node: '>=6 <7 || >=8'} 527 | 528 | fs-minipass@1.2.7: 529 | resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==} 530 | 531 | fs-minipass@2.1.0: 532 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} 533 | engines: {node: '>= 8'} 534 | 535 | fs.realpath@1.0.0: 536 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 537 | 538 | fsevents@2.1.3: 539 | resolution: {integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==} 540 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 541 | os: [darwin] 542 | 543 | gauge@3.0.2: 544 | resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} 545 | engines: {node: '>=10'} 546 | deprecated: This package is no longer supported. 547 | 548 | generic-pool@3.4.2: 549 | resolution: {integrity: sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==} 550 | engines: {node: '>= 4'} 551 | 552 | get-stream@5.2.0: 553 | resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} 554 | engines: {node: '>=8'} 555 | 556 | glob-parent@5.1.2: 557 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 558 | engines: {node: '>= 6'} 559 | 560 | glob@7.2.3: 561 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 562 | deprecated: Glob versions prior to v9 are no longer supported 563 | 564 | graceful-fs@4.2.11: 565 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 566 | 567 | has-unicode@2.0.1: 568 | resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} 569 | 570 | http-errors@1.4.0: 571 | resolution: {integrity: sha512-oLjPqve1tuOl5aRhv8GK5eHpqP1C9fb+Ol+XTLjKfLltE44zdDbEdjPSbU7Ch5rSNsVFqZn97SrMmZLdu1/YMw==} 572 | engines: {node: '>= 0.6'} 573 | 574 | http-errors@1.7.3: 575 | resolution: {integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==} 576 | engines: {node: '>= 0.6'} 577 | 578 | https-proxy-agent@5.0.1: 579 | resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} 580 | engines: {node: '>= 6'} 581 | 582 | human-signals@1.1.1: 583 | resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} 584 | engines: {node: '>=8.12.0'} 585 | 586 | iconv-lite@0.4.24: 587 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 588 | engines: {node: '>=0.10.0'} 589 | 590 | inflight@1.0.6: 591 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 592 | deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 593 | 594 | inherits@2.0.1: 595 | resolution: {integrity: sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==} 596 | 597 | inherits@2.0.4: 598 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 599 | 600 | is-binary-path@2.1.0: 601 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 602 | engines: {node: '>=8'} 603 | 604 | is-extglob@2.1.1: 605 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 606 | engines: {node: '>=0.10.0'} 607 | 608 | is-fullwidth-code-point@3.0.0: 609 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 610 | engines: {node: '>=8'} 611 | 612 | is-glob@4.0.3: 613 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 614 | engines: {node: '>=0.10.0'} 615 | 616 | is-number@7.0.0: 617 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 618 | engines: {node: '>=0.12.0'} 619 | 620 | is-stream@2.0.1: 621 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} 622 | engines: {node: '>=8'} 623 | 624 | isarray@0.0.1: 625 | resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} 626 | 627 | isexe@2.0.0: 628 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 629 | 630 | json-schema-to-ts@1.6.4: 631 | resolution: {integrity: sha512-pR4yQ9DHz6itqswtHCm26mw45FSNfQ9rEQjosaZErhn5J3J2sIViQiz8rDaezjKAhFGpmsoczYVBgGHzFw/stA==} 632 | 633 | json-schema-traverse@0.4.1: 634 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 635 | 636 | json-schema-traverse@1.0.0: 637 | resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} 638 | 639 | jsonfile@4.0.0: 640 | resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 641 | 642 | jsonfile@6.1.0: 643 | resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} 644 | 645 | lru-cache@6.0.0: 646 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 647 | engines: {node: '>=10'} 648 | 649 | make-dir@3.1.0: 650 | resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} 651 | engines: {node: '>=8'} 652 | 653 | make-error@1.3.6: 654 | resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} 655 | 656 | merge-stream@2.0.0: 657 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 658 | 659 | merge2@1.4.1: 660 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 661 | engines: {node: '>= 8'} 662 | 663 | micro@9.3.5-canary.3: 664 | resolution: {integrity: sha512-viYIo9PefV+w9dvoIBh1gI44Mvx1BOk67B4BpC2QK77qdY0xZF0Q+vWLt/BII6cLkIc8rLmSIcJaB/OrXXKe1g==} 665 | engines: {node: '>= 8.0.0'} 666 | hasBin: true 667 | 668 | micromatch@4.0.8: 669 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 670 | engines: {node: '>=8.6'} 671 | 672 | mimic-fn@2.1.0: 673 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} 674 | engines: {node: '>=6'} 675 | 676 | minimatch@3.1.2: 677 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 678 | 679 | minimist@1.2.8: 680 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} 681 | 682 | minipass@2.9.0: 683 | resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==} 684 | 685 | minipass@3.3.6: 686 | resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} 687 | engines: {node: '>=8'} 688 | 689 | minipass@5.0.0: 690 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 691 | engines: {node: '>=8'} 692 | 693 | minizlib@1.3.3: 694 | resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==} 695 | 696 | minizlib@2.1.2: 697 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} 698 | engines: {node: '>= 8'} 699 | 700 | mkdirp@0.5.6: 701 | resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} 702 | hasBin: true 703 | 704 | mkdirp@1.0.4: 705 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} 706 | engines: {node: '>=10'} 707 | hasBin: true 708 | 709 | mri@1.2.0: 710 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 711 | engines: {node: '>=4'} 712 | 713 | ms@2.1.1: 714 | resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} 715 | 716 | ms@2.1.3: 717 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 718 | 719 | node-fetch@2.6.7: 720 | resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} 721 | engines: {node: 4.x || >=6.0.0} 722 | peerDependencies: 723 | encoding: ^0.1.0 724 | peerDependenciesMeta: 725 | encoding: 726 | optional: true 727 | 728 | node-fetch@2.6.9: 729 | resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==} 730 | engines: {node: 4.x || >=6.0.0} 731 | peerDependencies: 732 | encoding: ^0.1.0 733 | peerDependenciesMeta: 734 | encoding: 735 | optional: true 736 | 737 | node-fetch@2.7.0: 738 | resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} 739 | engines: {node: 4.x || >=6.0.0} 740 | peerDependencies: 741 | encoding: ^0.1.0 742 | peerDependenciesMeta: 743 | encoding: 744 | optional: true 745 | 746 | node-gyp-build@4.8.3: 747 | resolution: {integrity: sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==} 748 | hasBin: true 749 | 750 | nopt@5.0.0: 751 | resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} 752 | engines: {node: '>=6'} 753 | hasBin: true 754 | 755 | normalize-path@3.0.0: 756 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 757 | engines: {node: '>=0.10.0'} 758 | 759 | npm-run-path@4.0.1: 760 | resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} 761 | engines: {node: '>=8'} 762 | 763 | npmlog@5.0.1: 764 | resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} 765 | deprecated: This package is no longer supported. 766 | 767 | object-assign@4.1.1: 768 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 769 | engines: {node: '>=0.10.0'} 770 | 771 | once@1.3.3: 772 | resolution: {integrity: sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==} 773 | 774 | once@1.4.0: 775 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 776 | 777 | onetime@5.1.2: 778 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} 779 | engines: {node: '>=6'} 780 | 781 | os-paths@4.4.0: 782 | resolution: {integrity: sha512-wrAwOeXp1RRMFfQY8Sy7VaGVmPocaLwSFOYCGKSyo8qmJ+/yaafCl5BCA1IQZWqFSRBrKDYFeR9d/VyQzfH/jg==} 783 | engines: {node: '>= 6.0'} 784 | 785 | p-finally@2.0.1: 786 | resolution: {integrity: sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==} 787 | engines: {node: '>=8'} 788 | 789 | parse-ms@2.1.0: 790 | resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==} 791 | engines: {node: '>=6'} 792 | 793 | path-browserify@1.0.1: 794 | resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} 795 | 796 | path-is-absolute@1.0.1: 797 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 798 | engines: {node: '>=0.10.0'} 799 | 800 | path-key@3.1.1: 801 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 802 | engines: {node: '>=8'} 803 | 804 | path-match@1.2.4: 805 | resolution: {integrity: sha512-UWlehEdqu36jmh4h5CWJ7tARp1OEVKGHKm6+dg9qMq5RKUTV5WJrGgaZ3dN2m7WFAXDbjlHzvJvL/IUpy84Ktw==} 806 | 807 | path-to-regexp@1.9.0: 808 | resolution: {integrity: sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==} 809 | 810 | path-to-regexp@6.1.0: 811 | resolution: {integrity: sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw==} 812 | 813 | path-to-regexp@6.2.1: 814 | resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} 815 | 816 | pend@1.2.0: 817 | resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} 818 | 819 | picocolors@1.0.0: 820 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 821 | 822 | picomatch@2.3.1: 823 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 824 | engines: {node: '>=8.6'} 825 | 826 | pretty-ms@7.0.1: 827 | resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==} 828 | engines: {node: '>=10'} 829 | 830 | promisepipe@3.0.0: 831 | resolution: {integrity: sha512-V6TbZDJ/ZswevgkDNpGt/YqNCiZP9ASfgU+p83uJE6NrGtvSGoOcHLiDCqkMs2+yg7F5qHdLV8d0aS8O26G/KA==} 832 | 833 | pump@3.0.2: 834 | resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} 835 | 836 | punycode@2.3.1: 837 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 838 | engines: {node: '>=6'} 839 | 840 | queue-microtask@1.2.3: 841 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 842 | 843 | raw-body@2.4.1: 844 | resolution: {integrity: sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==} 845 | engines: {node: '>= 0.8'} 846 | 847 | readable-stream@3.6.2: 848 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} 849 | engines: {node: '>= 6'} 850 | 851 | readdirp@3.3.0: 852 | resolution: {integrity: sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==} 853 | engines: {node: '>=8.10.0'} 854 | 855 | require-from-string@2.0.2: 856 | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 857 | engines: {node: '>=0.10.0'} 858 | 859 | resolve-from@5.0.0: 860 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 861 | engines: {node: '>=8'} 862 | 863 | reusify@1.0.4: 864 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 865 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 866 | 867 | rimraf@3.0.2: 868 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 869 | deprecated: Rimraf versions prior to v4 are no longer supported 870 | hasBin: true 871 | 872 | run-parallel@1.2.0: 873 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 874 | 875 | safe-buffer@5.2.1: 876 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 877 | 878 | safer-buffer@2.1.2: 879 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 880 | 881 | semver@6.3.1: 882 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 883 | hasBin: true 884 | 885 | semver@7.3.5: 886 | resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} 887 | engines: {node: '>=10'} 888 | hasBin: true 889 | 890 | semver@7.6.3: 891 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 892 | engines: {node: '>=10'} 893 | hasBin: true 894 | 895 | set-blocking@2.0.0: 896 | resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} 897 | 898 | setprototypeof@1.1.1: 899 | resolution: {integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==} 900 | 901 | shebang-command@2.0.0: 902 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 903 | engines: {node: '>=8'} 904 | 905 | shebang-regex@3.0.0: 906 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 907 | engines: {node: '>=8'} 908 | 909 | signal-exit@3.0.7: 910 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 911 | 912 | signal-exit@4.0.2: 913 | resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} 914 | engines: {node: '>=14'} 915 | 916 | stat-mode@0.3.0: 917 | resolution: {integrity: sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng==} 918 | 919 | statuses@1.5.0: 920 | resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} 921 | engines: {node: '>= 0.6'} 922 | 923 | stream-to-array@2.3.0: 924 | resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==} 925 | 926 | stream-to-promise@2.2.0: 927 | resolution: {integrity: sha512-HAGUASw8NT0k8JvIVutB2Y/9iBk7gpgEyAudXwNJmZERdMITGdajOa4VJfD/kNiA3TppQpTP4J+CtcHwdzKBAw==} 928 | 929 | string-width@4.2.3: 930 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 931 | engines: {node: '>=8'} 932 | 933 | string_decoder@1.3.0: 934 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} 935 | 936 | strip-ansi@6.0.1: 937 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 938 | engines: {node: '>=8'} 939 | 940 | strip-final-newline@2.0.0: 941 | resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} 942 | engines: {node: '>=6'} 943 | 944 | tar@4.4.18: 945 | resolution: {integrity: sha512-ZuOtqqmkV9RE1+4odd+MhBpibmCxNP6PJhH/h2OqNuotTX7/XHPZQJv2pKvWMplFH9SIZZhitehh6vBH6LO8Pg==} 946 | engines: {node: '>=4.5'} 947 | 948 | tar@6.2.1: 949 | resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} 950 | engines: {node: '>=10'} 951 | 952 | time-span@4.0.0: 953 | resolution: {integrity: sha512-MyqZCTGLDZ77u4k+jqg4UlrzPTPZ49NDlaekU6uuFaJLzPIN1woaRXCbGeqOfxwc3Y37ZROGAJ614Rdv7Olt+g==} 954 | engines: {node: '>=10'} 955 | 956 | to-regex-range@5.0.1: 957 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 958 | engines: {node: '>=8.0'} 959 | 960 | toidentifier@1.0.0: 961 | resolution: {integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==} 962 | engines: {node: '>=0.6'} 963 | 964 | tr46@0.0.3: 965 | resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 966 | 967 | tree-kill@1.2.2: 968 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 969 | hasBin: true 970 | 971 | ts-morph@12.0.0: 972 | resolution: {integrity: sha512-VHC8XgU2fFW7yO1f/b3mxKDje1vmyzFXHWzOYmKEkCEwcLjDtbdLgBQviqj4ZwP4MJkQtRo6Ha2I29lq/B+VxA==} 973 | 974 | ts-node@10.9.1: 975 | resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} 976 | hasBin: true 977 | peerDependencies: 978 | '@swc/core': '>=1.2.50' 979 | '@swc/wasm': '>=1.2.50' 980 | '@types/node': '*' 981 | typescript: '>=2.7' 982 | peerDependenciesMeta: 983 | '@swc/core': 984 | optional: true 985 | '@swc/wasm': 986 | optional: true 987 | 988 | ts-toolbelt@6.15.5: 989 | resolution: {integrity: sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==} 990 | 991 | typescript@4.9.5: 992 | resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} 993 | engines: {node: '>=4.2.0'} 994 | hasBin: true 995 | 996 | typescript@5.6.3: 997 | resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} 998 | engines: {node: '>=14.17'} 999 | hasBin: true 1000 | 1001 | uid-promise@1.0.0: 1002 | resolution: {integrity: sha512-R8375j0qwXyIu/7R0tjdF06/sElHqbmdmWC9M2qQHpEVbvE4I5+38KJI7LUUmQMp7NVq4tKHiBMkT0NFM453Ig==} 1003 | 1004 | undici-types@6.19.8: 1005 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 1006 | 1007 | undici@5.26.5: 1008 | resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==} 1009 | engines: {node: '>=14.0'} 1010 | 1011 | universalify@0.1.2: 1012 | resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 1013 | engines: {node: '>= 4.0.0'} 1014 | 1015 | universalify@2.0.1: 1016 | resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} 1017 | engines: {node: '>= 10.0.0'} 1018 | 1019 | unpipe@1.0.0: 1020 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} 1021 | engines: {node: '>= 0.8'} 1022 | 1023 | uri-js@4.4.1: 1024 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1025 | 1026 | util-deprecate@1.0.2: 1027 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1028 | 1029 | uuid@3.3.2: 1030 | resolution: {integrity: sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==} 1031 | deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. 1032 | hasBin: true 1033 | 1034 | v8-compile-cache-lib@3.0.1: 1035 | resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} 1036 | 1037 | vercel@32.7.2: 1038 | resolution: {integrity: sha512-esyeo67OZ/f7usKFCrx6NSjsvpo/BP/C8Mfron2uiCb4vXVcjkwOM7TwliHx6b0DbXjpzomdGVUHKRs34VNn2Q==} 1039 | engines: {node: '>= 16'} 1040 | hasBin: true 1041 | 1042 | web-vitals@0.2.4: 1043 | resolution: {integrity: sha512-6BjspCO9VriYy12z356nL6JBS0GYeEcA457YyRzD+dD6XYCQ75NKhcOHUMHentOE7OcVCIXXDvOm0jKFfQG2Gg==} 1044 | 1045 | webidl-conversions@3.0.1: 1046 | resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} 1047 | 1048 | whatwg-url@5.0.0: 1049 | resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} 1050 | 1051 | which@2.0.2: 1052 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1053 | engines: {node: '>= 8'} 1054 | hasBin: true 1055 | 1056 | wide-align@1.1.5: 1057 | resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} 1058 | 1059 | wrappy@1.0.2: 1060 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1061 | 1062 | xdg-app-paths@5.1.0: 1063 | resolution: {integrity: sha512-RAQ3WkPf4KTU1A8RtFx3gWywzVKe00tfOPFfl2NDGqbIFENQO4kqAJp7mhQjNj/33W5x5hiWWUdyfPq/5SU3QA==} 1064 | engines: {node: '>=6'} 1065 | 1066 | xdg-portable@7.3.0: 1067 | resolution: {integrity: sha512-sqMMuL1rc0FmMBOzCpd0yuy9trqF2yTTVe+E9ogwCSWQCdDEtQUwrZPT6AxqtsFGRNxycgncbP/xmOOSPw5ZUw==} 1068 | engines: {node: '>= 6.0'} 1069 | 1070 | yallist@3.1.1: 1071 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 1072 | 1073 | yallist@4.0.0: 1074 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1075 | 1076 | yauzl-clone@1.0.4: 1077 | resolution: {integrity: sha512-igM2RRCf3k8TvZoxR2oguuw4z1xasOnA31joCqHIyLkeWrvAc2Jgay5ISQ2ZplinkoGaJ6orCz56Ey456c5ESA==} 1078 | engines: {node: '>=6'} 1079 | 1080 | yauzl-promise@2.1.3: 1081 | resolution: {integrity: sha512-A1pf6fzh6eYkK0L4Qp7g9jzJSDrM6nN0bOn5T0IbY4Yo3w+YkWlHFkJP7mzknMXjqusHFHlKsK2N+4OLsK2MRA==} 1082 | engines: {node: '>=6'} 1083 | 1084 | yauzl@2.10.0: 1085 | resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} 1086 | 1087 | yn@3.1.1: 1088 | resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} 1089 | engines: {node: '>=6'} 1090 | 1091 | snapshots: 1092 | 1093 | '@cspotcode/source-map-support@0.8.1': 1094 | dependencies: 1095 | '@jridgewell/trace-mapping': 0.3.9 1096 | 1097 | '@edge-runtime/cookies@3.4.1': {} 1098 | 1099 | '@edge-runtime/format@2.2.0': {} 1100 | 1101 | '@edge-runtime/node-utils@2.2.1': 1102 | dependencies: 1103 | '@edge-runtime/cookies': 3.4.1 1104 | 1105 | '@edge-runtime/ponyfill@2.4.1': {} 1106 | 1107 | '@edge-runtime/primitives@4.0.5': {} 1108 | 1109 | '@edge-runtime/vm@3.1.7': 1110 | dependencies: 1111 | '@edge-runtime/primitives': 4.0.5 1112 | 1113 | '@fastify/busboy@2.1.1': {} 1114 | 1115 | '@jridgewell/resolve-uri@3.1.2': {} 1116 | 1117 | '@jridgewell/sourcemap-codec@1.5.0': {} 1118 | 1119 | '@jridgewell/trace-mapping@0.3.9': 1120 | dependencies: 1121 | '@jridgewell/resolve-uri': 3.1.2 1122 | '@jridgewell/sourcemap-codec': 1.5.0 1123 | 1124 | '@mapbox/node-pre-gyp@1.0.11': 1125 | dependencies: 1126 | detect-libc: 2.0.3 1127 | https-proxy-agent: 5.0.1 1128 | make-dir: 3.1.0 1129 | node-fetch: 2.7.0 1130 | nopt: 5.0.0 1131 | npmlog: 5.0.1 1132 | rimraf: 3.0.2 1133 | semver: 7.6.3 1134 | tar: 6.2.1 1135 | transitivePeerDependencies: 1136 | - encoding 1137 | - supports-color 1138 | 1139 | '@nodelib/fs.scandir@2.1.5': 1140 | dependencies: 1141 | '@nodelib/fs.stat': 2.0.5 1142 | run-parallel: 1.2.0 1143 | 1144 | '@nodelib/fs.stat@2.0.5': {} 1145 | 1146 | '@nodelib/fs.walk@1.2.8': 1147 | dependencies: 1148 | '@nodelib/fs.scandir': 2.1.5 1149 | fastq: 1.17.1 1150 | 1151 | '@rollup/pluginutils@4.2.1': 1152 | dependencies: 1153 | estree-walker: 2.0.2 1154 | picomatch: 2.3.1 1155 | 1156 | '@sinclair/typebox@0.25.24': {} 1157 | 1158 | '@tootallnate/once@2.0.0': {} 1159 | 1160 | '@ts-morph/common@0.11.1': 1161 | dependencies: 1162 | fast-glob: 3.3.2 1163 | minimatch: 3.1.2 1164 | mkdirp: 1.0.4 1165 | path-browserify: 1.0.1 1166 | 1167 | '@tsconfig/node10@1.0.11': {} 1168 | 1169 | '@tsconfig/node12@1.0.11': {} 1170 | 1171 | '@tsconfig/node14@1.0.3': {} 1172 | 1173 | '@tsconfig/node16@1.0.4': {} 1174 | 1175 | '@types/json-schema@7.0.15': {} 1176 | 1177 | '@types/node@14.18.33': {} 1178 | 1179 | '@types/node@22.9.0': 1180 | dependencies: 1181 | undici-types: 6.19.8 1182 | 1183 | '@vercel/build-utils@7.3.0': {} 1184 | 1185 | '@vercel/error-utils@2.0.2': {} 1186 | 1187 | '@vercel/fun@1.1.0': 1188 | dependencies: 1189 | '@tootallnate/once': 2.0.0 1190 | async-listen: 1.2.0 1191 | debug: 4.1.1 1192 | execa: 3.2.0 1193 | fs-extra: 8.1.0 1194 | generic-pool: 3.4.2 1195 | micro: 9.3.5-canary.3 1196 | ms: 2.1.1 1197 | node-fetch: 2.6.7 1198 | path-match: 1.2.4 1199 | promisepipe: 3.0.0 1200 | semver: 7.3.5 1201 | stat-mode: 0.3.0 1202 | stream-to-promise: 2.2.0 1203 | tar: 4.4.18 1204 | tree-kill: 1.2.2 1205 | uid-promise: 1.0.0 1206 | uuid: 3.3.2 1207 | xdg-app-paths: 5.1.0 1208 | yauzl-promise: 2.1.3 1209 | transitivePeerDependencies: 1210 | - encoding 1211 | - supports-color 1212 | 1213 | '@vercel/functions@1.5.0': {} 1214 | 1215 | '@vercel/gatsby-plugin-vercel-analytics@1.0.11': 1216 | dependencies: 1217 | web-vitals: 0.2.4 1218 | 1219 | '@vercel/gatsby-plugin-vercel-builder@2.0.12': 1220 | dependencies: 1221 | '@sinclair/typebox': 0.25.24 1222 | '@vercel/build-utils': 7.3.0 1223 | '@vercel/routing-utils': 3.1.0 1224 | esbuild: 0.14.47 1225 | etag: 1.8.1 1226 | fs-extra: 11.1.0 1227 | 1228 | '@vercel/go@3.0.4': {} 1229 | 1230 | '@vercel/hydrogen@1.0.1': 1231 | dependencies: 1232 | '@vercel/static-config': 3.0.0 1233 | ts-morph: 12.0.0 1234 | 1235 | '@vercel/next@4.0.15': 1236 | dependencies: 1237 | '@vercel/nft': 0.24.2 1238 | transitivePeerDependencies: 1239 | - encoding 1240 | - supports-color 1241 | 1242 | '@vercel/nft@0.24.2': 1243 | dependencies: 1244 | '@mapbox/node-pre-gyp': 1.0.11 1245 | '@rollup/pluginutils': 4.2.1 1246 | acorn: 8.14.0 1247 | async-sema: 3.1.1 1248 | bindings: 1.5.0 1249 | estree-walker: 2.0.2 1250 | glob: 7.2.3 1251 | graceful-fs: 4.2.11 1252 | micromatch: 4.0.8 1253 | node-gyp-build: 4.8.3 1254 | resolve-from: 5.0.0 1255 | transitivePeerDependencies: 1256 | - encoding 1257 | - supports-color 1258 | 1259 | '@vercel/node@3.0.12': 1260 | dependencies: 1261 | '@edge-runtime/node-utils': 2.2.1 1262 | '@edge-runtime/primitives': 4.0.5 1263 | '@edge-runtime/vm': 3.1.7 1264 | '@types/node': 14.18.33 1265 | '@vercel/build-utils': 7.3.0 1266 | '@vercel/error-utils': 2.0.2 1267 | '@vercel/nft': 0.24.2 1268 | '@vercel/static-config': 3.0.0 1269 | async-listen: 3.0.0 1270 | edge-runtime: 2.5.7 1271 | esbuild: 0.14.47 1272 | etag: 1.8.1 1273 | exit-hook: 2.2.1 1274 | node-fetch: 2.6.9 1275 | path-to-regexp: 6.2.1 1276 | ts-morph: 12.0.0 1277 | ts-node: 10.9.1(@types/node@14.18.33)(typescript@4.9.5) 1278 | typescript: 4.9.5 1279 | undici: 5.26.5 1280 | transitivePeerDependencies: 1281 | - '@swc/core' 1282 | - '@swc/wasm' 1283 | - encoding 1284 | - supports-color 1285 | 1286 | '@vercel/python@4.1.0': {} 1287 | 1288 | '@vercel/redwood@2.0.5': 1289 | dependencies: 1290 | '@vercel/nft': 0.24.2 1291 | '@vercel/routing-utils': 3.1.0 1292 | semver: 6.3.1 1293 | transitivePeerDependencies: 1294 | - encoding 1295 | - supports-color 1296 | 1297 | '@vercel/remix-builder@2.0.14': 1298 | dependencies: 1299 | '@vercel/nft': 0.24.2 1300 | '@vercel/static-config': 3.0.0 1301 | ts-morph: 12.0.0 1302 | transitivePeerDependencies: 1303 | - encoding 1304 | - supports-color 1305 | 1306 | '@vercel/routing-utils@3.1.0': 1307 | dependencies: 1308 | path-to-regexp: 6.1.0 1309 | optionalDependencies: 1310 | ajv: 6.12.6 1311 | 1312 | '@vercel/ruby@2.0.4': {} 1313 | 1314 | '@vercel/static-build@2.0.14': 1315 | dependencies: 1316 | '@vercel/gatsby-plugin-vercel-analytics': 1.0.11 1317 | '@vercel/gatsby-plugin-vercel-builder': 2.0.12 1318 | '@vercel/static-config': 3.0.0 1319 | ts-morph: 12.0.0 1320 | 1321 | '@vercel/static-config@3.0.0': 1322 | dependencies: 1323 | ajv: 8.6.3 1324 | json-schema-to-ts: 1.6.4 1325 | ts-morph: 12.0.0 1326 | 1327 | abbrev@1.1.1: {} 1328 | 1329 | acorn-walk@8.3.4: 1330 | dependencies: 1331 | acorn: 8.14.0 1332 | 1333 | acorn@8.14.0: {} 1334 | 1335 | agent-base@6.0.2: 1336 | dependencies: 1337 | debug: 4.3.7 1338 | transitivePeerDependencies: 1339 | - supports-color 1340 | 1341 | ajv@6.12.6: 1342 | dependencies: 1343 | fast-deep-equal: 3.1.3 1344 | fast-json-stable-stringify: 2.1.0 1345 | json-schema-traverse: 0.4.1 1346 | uri-js: 4.4.1 1347 | optional: true 1348 | 1349 | ajv@8.6.3: 1350 | dependencies: 1351 | fast-deep-equal: 3.1.3 1352 | json-schema-traverse: 1.0.0 1353 | require-from-string: 2.0.2 1354 | uri-js: 4.4.1 1355 | 1356 | ansi-regex@5.0.1: {} 1357 | 1358 | any-promise@1.3.0: {} 1359 | 1360 | anymatch@3.1.3: 1361 | dependencies: 1362 | normalize-path: 3.0.0 1363 | picomatch: 2.3.1 1364 | 1365 | aproba@2.0.0: {} 1366 | 1367 | are-we-there-yet@2.0.0: 1368 | dependencies: 1369 | delegates: 1.0.0 1370 | readable-stream: 3.6.2 1371 | 1372 | arg@4.1.0: {} 1373 | 1374 | arg@4.1.3: {} 1375 | 1376 | async-listen@1.2.0: {} 1377 | 1378 | async-listen@3.0.0: {} 1379 | 1380 | async-listen@3.0.1: {} 1381 | 1382 | async-sema@3.1.1: {} 1383 | 1384 | balanced-match@1.0.2: {} 1385 | 1386 | binary-extensions@2.3.0: {} 1387 | 1388 | bindings@1.5.0: 1389 | dependencies: 1390 | file-uri-to-path: 1.0.0 1391 | 1392 | brace-expansion@1.1.11: 1393 | dependencies: 1394 | balanced-match: 1.0.2 1395 | concat-map: 0.0.1 1396 | 1397 | braces@3.0.3: 1398 | dependencies: 1399 | fill-range: 7.1.1 1400 | 1401 | buffer-crc32@0.2.13: {} 1402 | 1403 | bytes@3.1.0: {} 1404 | 1405 | chokidar@3.3.1: 1406 | dependencies: 1407 | anymatch: 3.1.3 1408 | braces: 3.0.3 1409 | glob-parent: 5.1.2 1410 | is-binary-path: 2.1.0 1411 | is-glob: 4.0.3 1412 | normalize-path: 3.0.0 1413 | readdirp: 3.3.0 1414 | optionalDependencies: 1415 | fsevents: 2.1.3 1416 | 1417 | chownr@1.1.4: {} 1418 | 1419 | chownr@2.0.0: {} 1420 | 1421 | code-block-writer@10.1.1: {} 1422 | 1423 | color-support@1.1.3: {} 1424 | 1425 | concat-map@0.0.1: {} 1426 | 1427 | console-control-strings@1.1.0: {} 1428 | 1429 | content-type@1.0.4: {} 1430 | 1431 | convert-hrtime@3.0.0: {} 1432 | 1433 | create-require@1.1.1: {} 1434 | 1435 | cross-spawn@7.0.5: 1436 | dependencies: 1437 | path-key: 3.1.1 1438 | shebang-command: 2.0.0 1439 | which: 2.0.2 1440 | 1441 | debug@4.1.1: 1442 | dependencies: 1443 | ms: 2.1.1 1444 | 1445 | debug@4.3.7: 1446 | dependencies: 1447 | ms: 2.1.3 1448 | 1449 | delegates@1.0.0: {} 1450 | 1451 | depd@1.1.2: {} 1452 | 1453 | detect-libc@2.0.3: {} 1454 | 1455 | diff@4.0.2: {} 1456 | 1457 | edge-runtime@2.5.7: 1458 | dependencies: 1459 | '@edge-runtime/format': 2.2.0 1460 | '@edge-runtime/ponyfill': 2.4.1 1461 | '@edge-runtime/vm': 3.1.7 1462 | async-listen: 3.0.1 1463 | mri: 1.2.0 1464 | picocolors: 1.0.0 1465 | pretty-ms: 7.0.1 1466 | signal-exit: 4.0.2 1467 | time-span: 4.0.0 1468 | 1469 | emoji-regex@8.0.0: {} 1470 | 1471 | end-of-stream@1.1.0: 1472 | dependencies: 1473 | once: 1.3.3 1474 | 1475 | end-of-stream@1.4.4: 1476 | dependencies: 1477 | once: 1.4.0 1478 | 1479 | esbuild-android-64@0.14.47: 1480 | optional: true 1481 | 1482 | esbuild-android-arm64@0.14.47: 1483 | optional: true 1484 | 1485 | esbuild-darwin-64@0.14.47: 1486 | optional: true 1487 | 1488 | esbuild-darwin-arm64@0.14.47: 1489 | optional: true 1490 | 1491 | esbuild-freebsd-64@0.14.47: 1492 | optional: true 1493 | 1494 | esbuild-freebsd-arm64@0.14.47: 1495 | optional: true 1496 | 1497 | esbuild-linux-32@0.14.47: 1498 | optional: true 1499 | 1500 | esbuild-linux-64@0.14.47: 1501 | optional: true 1502 | 1503 | esbuild-linux-arm64@0.14.47: 1504 | optional: true 1505 | 1506 | esbuild-linux-arm@0.14.47: 1507 | optional: true 1508 | 1509 | esbuild-linux-mips64le@0.14.47: 1510 | optional: true 1511 | 1512 | esbuild-linux-ppc64le@0.14.47: 1513 | optional: true 1514 | 1515 | esbuild-linux-riscv64@0.14.47: 1516 | optional: true 1517 | 1518 | esbuild-linux-s390x@0.14.47: 1519 | optional: true 1520 | 1521 | esbuild-netbsd-64@0.14.47: 1522 | optional: true 1523 | 1524 | esbuild-openbsd-64@0.14.47: 1525 | optional: true 1526 | 1527 | esbuild-sunos-64@0.14.47: 1528 | optional: true 1529 | 1530 | esbuild-windows-32@0.14.47: 1531 | optional: true 1532 | 1533 | esbuild-windows-64@0.14.47: 1534 | optional: true 1535 | 1536 | esbuild-windows-arm64@0.14.47: 1537 | optional: true 1538 | 1539 | esbuild@0.14.47: 1540 | optionalDependencies: 1541 | esbuild-android-64: 0.14.47 1542 | esbuild-android-arm64: 0.14.47 1543 | esbuild-darwin-64: 0.14.47 1544 | esbuild-darwin-arm64: 0.14.47 1545 | esbuild-freebsd-64: 0.14.47 1546 | esbuild-freebsd-arm64: 0.14.47 1547 | esbuild-linux-32: 0.14.47 1548 | esbuild-linux-64: 0.14.47 1549 | esbuild-linux-arm: 0.14.47 1550 | esbuild-linux-arm64: 0.14.47 1551 | esbuild-linux-mips64le: 0.14.47 1552 | esbuild-linux-ppc64le: 0.14.47 1553 | esbuild-linux-riscv64: 0.14.47 1554 | esbuild-linux-s390x: 0.14.47 1555 | esbuild-netbsd-64: 0.14.47 1556 | esbuild-openbsd-64: 0.14.47 1557 | esbuild-sunos-64: 0.14.47 1558 | esbuild-windows-32: 0.14.47 1559 | esbuild-windows-64: 0.14.47 1560 | esbuild-windows-arm64: 0.14.47 1561 | 1562 | estree-walker@2.0.2: {} 1563 | 1564 | etag@1.8.1: {} 1565 | 1566 | events-intercept@2.0.0: {} 1567 | 1568 | execa@3.2.0: 1569 | dependencies: 1570 | cross-spawn: 7.0.5 1571 | get-stream: 5.2.0 1572 | human-signals: 1.1.1 1573 | is-stream: 2.0.1 1574 | merge-stream: 2.0.0 1575 | npm-run-path: 4.0.1 1576 | onetime: 5.1.2 1577 | p-finally: 2.0.1 1578 | signal-exit: 3.0.7 1579 | strip-final-newline: 2.0.0 1580 | 1581 | exit-hook@2.2.1: {} 1582 | 1583 | fast-deep-equal@3.1.3: {} 1584 | 1585 | fast-glob@3.3.2: 1586 | dependencies: 1587 | '@nodelib/fs.stat': 2.0.5 1588 | '@nodelib/fs.walk': 1.2.8 1589 | glob-parent: 5.1.2 1590 | merge2: 1.4.1 1591 | micromatch: 4.0.8 1592 | 1593 | fast-json-stable-stringify@2.1.0: 1594 | optional: true 1595 | 1596 | fastq@1.17.1: 1597 | dependencies: 1598 | reusify: 1.0.4 1599 | 1600 | fd-slicer@1.1.0: 1601 | dependencies: 1602 | pend: 1.2.0 1603 | 1604 | file-uri-to-path@1.0.0: {} 1605 | 1606 | fill-range@7.1.1: 1607 | dependencies: 1608 | to-regex-range: 5.0.1 1609 | 1610 | fs-extra@11.1.0: 1611 | dependencies: 1612 | graceful-fs: 4.2.11 1613 | jsonfile: 6.1.0 1614 | universalify: 2.0.1 1615 | 1616 | fs-extra@8.1.0: 1617 | dependencies: 1618 | graceful-fs: 4.2.11 1619 | jsonfile: 4.0.0 1620 | universalify: 0.1.2 1621 | 1622 | fs-minipass@1.2.7: 1623 | dependencies: 1624 | minipass: 2.9.0 1625 | 1626 | fs-minipass@2.1.0: 1627 | dependencies: 1628 | minipass: 3.3.6 1629 | 1630 | fs.realpath@1.0.0: {} 1631 | 1632 | fsevents@2.1.3: 1633 | optional: true 1634 | 1635 | gauge@3.0.2: 1636 | dependencies: 1637 | aproba: 2.0.0 1638 | color-support: 1.1.3 1639 | console-control-strings: 1.1.0 1640 | has-unicode: 2.0.1 1641 | object-assign: 4.1.1 1642 | signal-exit: 3.0.7 1643 | string-width: 4.2.3 1644 | strip-ansi: 6.0.1 1645 | wide-align: 1.1.5 1646 | 1647 | generic-pool@3.4.2: {} 1648 | 1649 | get-stream@5.2.0: 1650 | dependencies: 1651 | pump: 3.0.2 1652 | 1653 | glob-parent@5.1.2: 1654 | dependencies: 1655 | is-glob: 4.0.3 1656 | 1657 | glob@7.2.3: 1658 | dependencies: 1659 | fs.realpath: 1.0.0 1660 | inflight: 1.0.6 1661 | inherits: 2.0.4 1662 | minimatch: 3.1.2 1663 | once: 1.4.0 1664 | path-is-absolute: 1.0.1 1665 | 1666 | graceful-fs@4.2.11: {} 1667 | 1668 | has-unicode@2.0.1: {} 1669 | 1670 | http-errors@1.4.0: 1671 | dependencies: 1672 | inherits: 2.0.1 1673 | statuses: 1.5.0 1674 | 1675 | http-errors@1.7.3: 1676 | dependencies: 1677 | depd: 1.1.2 1678 | inherits: 2.0.4 1679 | setprototypeof: 1.1.1 1680 | statuses: 1.5.0 1681 | toidentifier: 1.0.0 1682 | 1683 | https-proxy-agent@5.0.1: 1684 | dependencies: 1685 | agent-base: 6.0.2 1686 | debug: 4.3.7 1687 | transitivePeerDependencies: 1688 | - supports-color 1689 | 1690 | human-signals@1.1.1: {} 1691 | 1692 | iconv-lite@0.4.24: 1693 | dependencies: 1694 | safer-buffer: 2.1.2 1695 | 1696 | inflight@1.0.6: 1697 | dependencies: 1698 | once: 1.4.0 1699 | wrappy: 1.0.2 1700 | 1701 | inherits@2.0.1: {} 1702 | 1703 | inherits@2.0.4: {} 1704 | 1705 | is-binary-path@2.1.0: 1706 | dependencies: 1707 | binary-extensions: 2.3.0 1708 | 1709 | is-extglob@2.1.1: {} 1710 | 1711 | is-fullwidth-code-point@3.0.0: {} 1712 | 1713 | is-glob@4.0.3: 1714 | dependencies: 1715 | is-extglob: 2.1.1 1716 | 1717 | is-number@7.0.0: {} 1718 | 1719 | is-stream@2.0.1: {} 1720 | 1721 | isarray@0.0.1: {} 1722 | 1723 | isexe@2.0.0: {} 1724 | 1725 | json-schema-to-ts@1.6.4: 1726 | dependencies: 1727 | '@types/json-schema': 7.0.15 1728 | ts-toolbelt: 6.15.5 1729 | 1730 | json-schema-traverse@0.4.1: 1731 | optional: true 1732 | 1733 | json-schema-traverse@1.0.0: {} 1734 | 1735 | jsonfile@4.0.0: 1736 | optionalDependencies: 1737 | graceful-fs: 4.2.11 1738 | 1739 | jsonfile@6.1.0: 1740 | dependencies: 1741 | universalify: 2.0.1 1742 | optionalDependencies: 1743 | graceful-fs: 4.2.11 1744 | 1745 | lru-cache@6.0.0: 1746 | dependencies: 1747 | yallist: 4.0.0 1748 | 1749 | make-dir@3.1.0: 1750 | dependencies: 1751 | semver: 6.3.1 1752 | 1753 | make-error@1.3.6: {} 1754 | 1755 | merge-stream@2.0.0: {} 1756 | 1757 | merge2@1.4.1: {} 1758 | 1759 | micro@9.3.5-canary.3: 1760 | dependencies: 1761 | arg: 4.1.0 1762 | content-type: 1.0.4 1763 | raw-body: 2.4.1 1764 | 1765 | micromatch@4.0.8: 1766 | dependencies: 1767 | braces: 3.0.3 1768 | picomatch: 2.3.1 1769 | 1770 | mimic-fn@2.1.0: {} 1771 | 1772 | minimatch@3.1.2: 1773 | dependencies: 1774 | brace-expansion: 1.1.11 1775 | 1776 | minimist@1.2.8: {} 1777 | 1778 | minipass@2.9.0: 1779 | dependencies: 1780 | safe-buffer: 5.2.1 1781 | yallist: 3.1.1 1782 | 1783 | minipass@3.3.6: 1784 | dependencies: 1785 | yallist: 4.0.0 1786 | 1787 | minipass@5.0.0: {} 1788 | 1789 | minizlib@1.3.3: 1790 | dependencies: 1791 | minipass: 2.9.0 1792 | 1793 | minizlib@2.1.2: 1794 | dependencies: 1795 | minipass: 3.3.6 1796 | yallist: 4.0.0 1797 | 1798 | mkdirp@0.5.6: 1799 | dependencies: 1800 | minimist: 1.2.8 1801 | 1802 | mkdirp@1.0.4: {} 1803 | 1804 | mri@1.2.0: {} 1805 | 1806 | ms@2.1.1: {} 1807 | 1808 | ms@2.1.3: {} 1809 | 1810 | node-fetch@2.6.7: 1811 | dependencies: 1812 | whatwg-url: 5.0.0 1813 | 1814 | node-fetch@2.6.9: 1815 | dependencies: 1816 | whatwg-url: 5.0.0 1817 | 1818 | node-fetch@2.7.0: 1819 | dependencies: 1820 | whatwg-url: 5.0.0 1821 | 1822 | node-gyp-build@4.8.3: {} 1823 | 1824 | nopt@5.0.0: 1825 | dependencies: 1826 | abbrev: 1.1.1 1827 | 1828 | normalize-path@3.0.0: {} 1829 | 1830 | npm-run-path@4.0.1: 1831 | dependencies: 1832 | path-key: 3.1.1 1833 | 1834 | npmlog@5.0.1: 1835 | dependencies: 1836 | are-we-there-yet: 2.0.0 1837 | console-control-strings: 1.1.0 1838 | gauge: 3.0.2 1839 | set-blocking: 2.0.0 1840 | 1841 | object-assign@4.1.1: {} 1842 | 1843 | once@1.3.3: 1844 | dependencies: 1845 | wrappy: 1.0.2 1846 | 1847 | once@1.4.0: 1848 | dependencies: 1849 | wrappy: 1.0.2 1850 | 1851 | onetime@5.1.2: 1852 | dependencies: 1853 | mimic-fn: 2.1.0 1854 | 1855 | os-paths@4.4.0: {} 1856 | 1857 | p-finally@2.0.1: {} 1858 | 1859 | parse-ms@2.1.0: {} 1860 | 1861 | path-browserify@1.0.1: {} 1862 | 1863 | path-is-absolute@1.0.1: {} 1864 | 1865 | path-key@3.1.1: {} 1866 | 1867 | path-match@1.2.4: 1868 | dependencies: 1869 | http-errors: 1.4.0 1870 | path-to-regexp: 1.9.0 1871 | 1872 | path-to-regexp@1.9.0: 1873 | dependencies: 1874 | isarray: 0.0.1 1875 | 1876 | path-to-regexp@6.1.0: {} 1877 | 1878 | path-to-regexp@6.2.1: {} 1879 | 1880 | pend@1.2.0: {} 1881 | 1882 | picocolors@1.0.0: {} 1883 | 1884 | picomatch@2.3.1: {} 1885 | 1886 | pretty-ms@7.0.1: 1887 | dependencies: 1888 | parse-ms: 2.1.0 1889 | 1890 | promisepipe@3.0.0: {} 1891 | 1892 | pump@3.0.2: 1893 | dependencies: 1894 | end-of-stream: 1.4.4 1895 | once: 1.4.0 1896 | 1897 | punycode@2.3.1: {} 1898 | 1899 | queue-microtask@1.2.3: {} 1900 | 1901 | raw-body@2.4.1: 1902 | dependencies: 1903 | bytes: 3.1.0 1904 | http-errors: 1.7.3 1905 | iconv-lite: 0.4.24 1906 | unpipe: 1.0.0 1907 | 1908 | readable-stream@3.6.2: 1909 | dependencies: 1910 | inherits: 2.0.4 1911 | string_decoder: 1.3.0 1912 | util-deprecate: 1.0.2 1913 | 1914 | readdirp@3.3.0: 1915 | dependencies: 1916 | picomatch: 2.3.1 1917 | 1918 | require-from-string@2.0.2: {} 1919 | 1920 | resolve-from@5.0.0: {} 1921 | 1922 | reusify@1.0.4: {} 1923 | 1924 | rimraf@3.0.2: 1925 | dependencies: 1926 | glob: 7.2.3 1927 | 1928 | run-parallel@1.2.0: 1929 | dependencies: 1930 | queue-microtask: 1.2.3 1931 | 1932 | safe-buffer@5.2.1: {} 1933 | 1934 | safer-buffer@2.1.2: {} 1935 | 1936 | semver@6.3.1: {} 1937 | 1938 | semver@7.3.5: 1939 | dependencies: 1940 | lru-cache: 6.0.0 1941 | 1942 | semver@7.6.3: {} 1943 | 1944 | set-blocking@2.0.0: {} 1945 | 1946 | setprototypeof@1.1.1: {} 1947 | 1948 | shebang-command@2.0.0: 1949 | dependencies: 1950 | shebang-regex: 3.0.0 1951 | 1952 | shebang-regex@3.0.0: {} 1953 | 1954 | signal-exit@3.0.7: {} 1955 | 1956 | signal-exit@4.0.2: {} 1957 | 1958 | stat-mode@0.3.0: {} 1959 | 1960 | statuses@1.5.0: {} 1961 | 1962 | stream-to-array@2.3.0: 1963 | dependencies: 1964 | any-promise: 1.3.0 1965 | 1966 | stream-to-promise@2.2.0: 1967 | dependencies: 1968 | any-promise: 1.3.0 1969 | end-of-stream: 1.1.0 1970 | stream-to-array: 2.3.0 1971 | 1972 | string-width@4.2.3: 1973 | dependencies: 1974 | emoji-regex: 8.0.0 1975 | is-fullwidth-code-point: 3.0.0 1976 | strip-ansi: 6.0.1 1977 | 1978 | string_decoder@1.3.0: 1979 | dependencies: 1980 | safe-buffer: 5.2.1 1981 | 1982 | strip-ansi@6.0.1: 1983 | dependencies: 1984 | ansi-regex: 5.0.1 1985 | 1986 | strip-final-newline@2.0.0: {} 1987 | 1988 | tar@4.4.18: 1989 | dependencies: 1990 | chownr: 1.1.4 1991 | fs-minipass: 1.2.7 1992 | minipass: 2.9.0 1993 | minizlib: 1.3.3 1994 | mkdirp: 0.5.6 1995 | safe-buffer: 5.2.1 1996 | yallist: 3.1.1 1997 | 1998 | tar@6.2.1: 1999 | dependencies: 2000 | chownr: 2.0.0 2001 | fs-minipass: 2.1.0 2002 | minipass: 5.0.0 2003 | minizlib: 2.1.2 2004 | mkdirp: 1.0.4 2005 | yallist: 4.0.0 2006 | 2007 | time-span@4.0.0: 2008 | dependencies: 2009 | convert-hrtime: 3.0.0 2010 | 2011 | to-regex-range@5.0.1: 2012 | dependencies: 2013 | is-number: 7.0.0 2014 | 2015 | toidentifier@1.0.0: {} 2016 | 2017 | tr46@0.0.3: {} 2018 | 2019 | tree-kill@1.2.2: {} 2020 | 2021 | ts-morph@12.0.0: 2022 | dependencies: 2023 | '@ts-morph/common': 0.11.1 2024 | code-block-writer: 10.1.1 2025 | 2026 | ts-node@10.9.1(@types/node@14.18.33)(typescript@4.9.5): 2027 | dependencies: 2028 | '@cspotcode/source-map-support': 0.8.1 2029 | '@tsconfig/node10': 1.0.11 2030 | '@tsconfig/node12': 1.0.11 2031 | '@tsconfig/node14': 1.0.3 2032 | '@tsconfig/node16': 1.0.4 2033 | '@types/node': 14.18.33 2034 | acorn: 8.14.0 2035 | acorn-walk: 8.3.4 2036 | arg: 4.1.3 2037 | create-require: 1.1.1 2038 | diff: 4.0.2 2039 | make-error: 1.3.6 2040 | typescript: 4.9.5 2041 | v8-compile-cache-lib: 3.0.1 2042 | yn: 3.1.1 2043 | 2044 | ts-toolbelt@6.15.5: {} 2045 | 2046 | typescript@4.9.5: {} 2047 | 2048 | typescript@5.6.3: {} 2049 | 2050 | uid-promise@1.0.0: {} 2051 | 2052 | undici-types@6.19.8: {} 2053 | 2054 | undici@5.26.5: 2055 | dependencies: 2056 | '@fastify/busboy': 2.1.1 2057 | 2058 | universalify@0.1.2: {} 2059 | 2060 | universalify@2.0.1: {} 2061 | 2062 | unpipe@1.0.0: {} 2063 | 2064 | uri-js@4.4.1: 2065 | dependencies: 2066 | punycode: 2.3.1 2067 | 2068 | util-deprecate@1.0.2: {} 2069 | 2070 | uuid@3.3.2: {} 2071 | 2072 | v8-compile-cache-lib@3.0.1: {} 2073 | 2074 | vercel@32.7.2: 2075 | dependencies: 2076 | '@vercel/build-utils': 7.3.0 2077 | '@vercel/fun': 1.1.0 2078 | '@vercel/go': 3.0.4 2079 | '@vercel/hydrogen': 1.0.1 2080 | '@vercel/next': 4.0.15 2081 | '@vercel/node': 3.0.12 2082 | '@vercel/python': 4.1.0 2083 | '@vercel/redwood': 2.0.5 2084 | '@vercel/remix-builder': 2.0.14 2085 | '@vercel/ruby': 2.0.4 2086 | '@vercel/static-build': 2.0.14 2087 | chokidar: 3.3.1 2088 | transitivePeerDependencies: 2089 | - '@swc/core' 2090 | - '@swc/wasm' 2091 | - encoding 2092 | - supports-color 2093 | 2094 | web-vitals@0.2.4: {} 2095 | 2096 | webidl-conversions@3.0.1: {} 2097 | 2098 | whatwg-url@5.0.0: 2099 | dependencies: 2100 | tr46: 0.0.3 2101 | webidl-conversions: 3.0.1 2102 | 2103 | which@2.0.2: 2104 | dependencies: 2105 | isexe: 2.0.0 2106 | 2107 | wide-align@1.1.5: 2108 | dependencies: 2109 | string-width: 4.2.3 2110 | 2111 | wrappy@1.0.2: {} 2112 | 2113 | xdg-app-paths@5.1.0: 2114 | dependencies: 2115 | xdg-portable: 7.3.0 2116 | 2117 | xdg-portable@7.3.0: 2118 | dependencies: 2119 | os-paths: 4.4.0 2120 | 2121 | yallist@3.1.1: {} 2122 | 2123 | yallist@4.0.0: {} 2124 | 2125 | yauzl-clone@1.0.4: 2126 | dependencies: 2127 | events-intercept: 2.0.0 2128 | 2129 | yauzl-promise@2.1.3: 2130 | dependencies: 2131 | yauzl: 2.10.0 2132 | yauzl-clone: 1.0.4 2133 | 2134 | yauzl@2.10.0: 2135 | dependencies: 2136 | buffer-crc32: 0.2.13 2137 | fd-slicer: 1.1.0 2138 | 2139 | yn@3.1.1: {} 2140 | --------------------------------------------------------------------------------