diff --git a/bun.lock b/bun.lock index ab6bd88c..c4095689 100644 --- a/bun.lock +++ b/bun.lock @@ -73,6 +73,8 @@ "@radix-ui/react-tooltip": "^1.1.4", "@semhub/core": "workspace:*", "@semhub/workers": "workspace:*", + "@sentry/react": "^8.54.0", + "@sentry/vite-plugin": "^3.1.2", "@tanstack/react-form": "^0.33.0", "@tanstack/react-query": "^5.59.6", "@tanstack/react-router": "^1.63.5", @@ -123,6 +125,7 @@ "@openauthjs/openauth": "*", "@semhub/core": "workspace:*", "@semhub/wrangler": "workspace:*", + "@sentry/cloudflare": "^8.54.0", "hono": "^4.6.5", }, "devDependencies": { @@ -550,6 +553,44 @@ "@semhub/wrangler": ["@semhub/wrangler@workspace:packages/wrangler"], + "@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@8.54.0", "", { "dependencies": { "@sentry/core": "8.54.0" } }, "sha512-DKWCqb4YQosKn6aD45fhKyzhkdG7N6goGFDeyTaJFREJDFVDXiNDsYZu30nJ6BxMM7uQIaARhPAC5BXfoED3pQ=="], + + "@sentry-internal/feedback": ["@sentry-internal/feedback@8.54.0", "", { "dependencies": { "@sentry/core": "8.54.0" } }, "sha512-nQqRacOXoElpE0L0ADxUUII0I3A94niqG9Z4Fmsw6057QvyrV/LvTiMQBop6r5qLjwMqK+T33iR4/NQI5RhsXQ=="], + + "@sentry-internal/replay": ["@sentry-internal/replay@8.54.0", "", { "dependencies": { "@sentry-internal/browser-utils": "8.54.0", "@sentry/core": "8.54.0" } }, "sha512-8xuBe06IaYIGJec53wUC12tY2q4z2Z0RPS2s1sLtbA00EvK1YDGuXp96IDD+HB9mnDMrQ/jW5f97g9TvPsPQUg=="], + + "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@8.54.0", "", { "dependencies": { "@sentry-internal/replay": "8.54.0", "@sentry/core": "8.54.0" } }, "sha512-K/On3OAUBeq/TV2n+1EvObKC+WMV9npVXpVyJqCCyn8HYMm8FUGzuxeajzm0mlW4wDTPCQor6mK9/IgOquUzCw=="], + + "@sentry/babel-plugin-component-annotate": ["@sentry/babel-plugin-component-annotate@3.1.2", "", {}, "sha512-5h2WXRJ6swKA0TwxHHryC8M2QyOfS9QhTAL6ElPfkEYe9HhJieXmxsDpyspbqAa26ccnCUcmwE5vL34jAjt4sQ=="], + + "@sentry/browser": ["@sentry/browser@8.54.0", "", { "dependencies": { "@sentry-internal/browser-utils": "8.54.0", "@sentry-internal/feedback": "8.54.0", "@sentry-internal/replay": "8.54.0", "@sentry-internal/replay-canvas": "8.54.0", "@sentry/core": "8.54.0" } }, "sha512-BgUtvxFHin0fS0CmJVKTLXXZcke0Av729IVfi+2fJ4COX8HO7/HAP02RKaSQGmL2HmvWYTfNZ7529AnUtrM4Rg=="], + + "@sentry/bundler-plugin-core": ["@sentry/bundler-plugin-core@3.1.2", "", { "dependencies": { "@babel/core": "^7.18.5", "@sentry/babel-plugin-component-annotate": "3.1.2", "@sentry/cli": "2.41.1", "dotenv": "^16.3.1", "find-up": "^5.0.0", "glob": "^9.3.2", "magic-string": "0.30.8", "unplugin": "1.0.1" } }, "sha512-lqOCvmOPzKiQenIMhmm5/mwCntwFy0dPZbVD28Dnr3MXpT1rIBg1HXjfnqQWFlMRbL9haSsWiY/TQyR/6b30YA=="], + + "@sentry/cli": ["@sentry/cli@2.41.1", "", { "dependencies": { "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.7", "progress": "^2.0.3", "proxy-from-env": "^1.1.0", "which": "^2.0.2" }, "optionalDependencies": { "@sentry/cli-darwin": "2.41.1", "@sentry/cli-linux-arm": "2.41.1", "@sentry/cli-linux-arm64": "2.41.1", "@sentry/cli-linux-i686": "2.41.1", "@sentry/cli-linux-x64": "2.41.1", "@sentry/cli-win32-i686": "2.41.1", "@sentry/cli-win32-x64": "2.41.1" }, "bin": { "sentry-cli": "bin/sentry-cli" } }, "sha512-0GVmDiTV7R1492wkVY4bGcfC0fSmRmQjuxaaPI8CIV9B2VP9pBVCUizi1mevXaaE4I3fM60LI+XYrKFEneuVog=="], + + "@sentry/cli-darwin": ["@sentry/cli-darwin@2.41.1", "", { "os": "darwin" }, "sha512-7pS3pu/SuhE6jOn3wptstAg6B5nUP878O6s+2svT7b5fKNfYUi/6NPK6dAveh2Ca0rwVq40TO4YFJabWMgTpdQ=="], + + "@sentry/cli-linux-arm": ["@sentry/cli-linux-arm@2.41.1", "", { "os": [ "linux", "freebsd", ], "cpu": "arm" }, "sha512-wNUvquD6qjOCczvuBGf9OiD29nuQ6yf8zzfyPJa5Bdx1QXuteKsKb6HBrMwuIR3liyuu0duzHd+H/+p1n541Hg=="], + + "@sentry/cli-linux-arm64": ["@sentry/cli-linux-arm64@2.41.1", "", { "os": [ "linux", "freebsd", ], "cpu": "arm64" }, "sha512-EzYCEnnENBnS5kpNW+2dBcrPZn1MVfywh2joGVQZTpmgDL5YFJ59VOd+K0XuEwqgFI8BSNI14KXZ75s4DD1/Vw=="], + + "@sentry/cli-linux-i686": ["@sentry/cli-linux-i686@2.41.1", "", { "os": [ "linux", "freebsd", ], "cpu": "ia32" }, "sha512-urpQCWrdYnSAsZY3udttuMV88wTJzKZL10xsrp7sjD/Hd+O6qSLVLkxebIlxts70jMLLFHYrQ2bkRg5kKuX6Fg=="], + + "@sentry/cli-linux-x64": ["@sentry/cli-linux-x64@2.41.1", "", { "os": [ "linux", "freebsd", ], "cpu": "x64" }, "sha512-ZqpYwHXAaK4MMEFlyaLYr6mJTmpy9qP6n30jGhLTW7kHKS3s6GPLCSlNmIfeClrInEt0963fM633ZRnXa04VPw=="], + + "@sentry/cli-win32-i686": ["@sentry/cli-win32-i686@2.41.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-AuRimCeVsx99DIOr9cwdYBHk39tlmAuPDdy2r16iNzY0InXs4xOys4gGzM7N4vlFQvFkzuc778Su0HkfasgprA=="], + + "@sentry/cli-win32-x64": ["@sentry/cli-win32-x64@2.41.1", "", { "os": "win32", "cpu": "x64" }, "sha512-6JcPvXGye61+wPp0xdzfc2YLE/Dcud8JdaK8VxLM3b/8+Em7E+UyliDu3uF8+YGUqizY5JYTd3fs17DC8DZhLw=="], + + "@sentry/cloudflare": ["@sentry/cloudflare@8.54.0", "", { "dependencies": { "@sentry/core": "8.54.0" }, "optionalDependencies": { "@cloudflare/workers-types": "^4.x" } }, "sha512-dikzUEE8p3p461r+psIr+M8JqjXTY4WKEVpsmlgyY7f1hdbgjErL/QXTX3lrmYljNmn6feHsrruGdeuASmMaNQ=="], + + "@sentry/core": ["@sentry/core@8.54.0", "", {}, "sha512-03bWf+D1j28unOocY/5FDB6bUHtYlm6m6ollVejhg45ZmK9iPjdtxNWbrLsjT1WRym0Tjzowu+A3p+eebYEv0Q=="], + + "@sentry/react": ["@sentry/react@8.54.0", "", { "dependencies": { "@sentry/browser": "8.54.0", "@sentry/core": "8.54.0", "hoist-non-react-statics": "^3.3.2" }, "peerDependencies": { "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, "sha512-42T/fp8snYN19Fy/2P0Mwotu4gcdy+1Lx+uYCNcYP1o7wNGigJ7qb27sW7W34GyCCHjoCCfQgeOqDQsyY8LC9w=="], + + "@sentry/vite-plugin": ["@sentry/vite-plugin@3.1.2", "", { "dependencies": { "@sentry/bundler-plugin-core": "3.1.2", "unplugin": "1.0.1" } }, "sha512-a927sabQKviA4PAs9cM3rFONHiVdfEHHkypmub+hFwJNL0sbeg/8uht0WyqDT5WjVT5pbyvLaKLDjGdwrRBY6Q=="], + "@sinclair/typebox": ["@sinclair/typebox@0.27.8", "", {}, "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="], "@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.3", "", {}, "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw=="], @@ -678,6 +719,8 @@ "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], + "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + "agentkeepalive": ["agentkeepalive@4.5.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew=="], "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], @@ -878,6 +921,8 @@ "domutils": ["domutils@3.1.0", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA=="], + "dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="], + "drizzle-kit": ["drizzle-kit@0.24.2", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.1", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-nXOaTSFiuIaTMhS8WJC2d4EBeIcN9OSt2A2cyFbQYBAZbi7lRsVGJNqDpEwPqYfJz38yxbY/UtbvBBahBfnExQ=="], "drizzle-orm": ["drizzle-orm@0.33.0", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=3", "@electric-sql/pglite": ">=0.1.1", "@libsql/client": "*", "@neondatabase/serverless": ">=0.1", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/react": ">=18", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=13.2.0", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "react": ">=18", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/react", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "knex", "kysely", "mysql2", "pg", "postgres", "react", "sql.js", "sqlite3"] }, "sha512-SHy72R2Rdkz0LEq0PSG/IdvnT3nGiWuRk+2tXZQ90GVq/XQhpCzu/EFT3V2rox+w8MlkBQxifF8pCStNYnERfA=="], @@ -994,6 +1039,8 @@ "fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="], + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], @@ -1016,7 +1063,7 @@ "get-tsconfig": ["get-tsconfig@4.8.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg=="], - "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + "glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -1054,6 +1101,8 @@ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], + "hono": ["hono@4.6.5", "", {}, "sha512-qsmN3V5fgtwdKARGLgwwHvcdLKursMd+YOt69eGpl1dUCJb8mCd7hZfyZnBYjxCegBG7qkJRQRUy2oO25yHcyQ=="], "hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], @@ -1062,6 +1111,8 @@ "htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], + "https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + "humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], @@ -1244,7 +1295,7 @@ "minimist-options": ["minimist-options@4.1.0", "", { "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", "kind-of": "^6.0.3" } }, "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A=="], - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], "mrmime": ["mrmime@1.0.1", "", {}, "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw=="], @@ -1376,10 +1427,14 @@ "printable-characters": ["printable-characters@1.0.42", "", {}, "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ=="], + "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], "proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="], + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], @@ -1666,6 +1721,8 @@ "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "webpack-sources": ["webpack-sources@3.2.3", "", {}, "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w=="], + "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], @@ -1854,6 +1911,14 @@ "@remix-run/web-stream/web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], + "@sentry/bundler-plugin-core/@babel/core": ["@babel/core@7.26.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.0", "@babel/generator": "^7.26.0", "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.0", "@babel/parser": "^7.26.0", "@babel/template": "^7.25.9", "@babel/traverse": "^7.25.9", "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg=="], + + "@sentry/bundler-plugin-core/magic-string": ["magic-string@0.30.8", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ=="], + + "@sentry/bundler-plugin-core/unplugin": ["unplugin@1.0.1", "", { "dependencies": { "acorn": "^8.8.1", "chokidar": "^3.5.3", "webpack-sources": "^3.2.3", "webpack-virtual-modules": "^0.5.0" } }, "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA=="], + + "@sentry/vite-plugin/unplugin": ["unplugin@1.0.1", "", { "dependencies": { "acorn": "^8.8.1", "chokidar": "^3.5.3", "webpack-sources": "^3.2.3", "webpack-virtual-modules": "^0.5.0" } }, "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA=="], + "@tanstack/react-store/react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], "@tanstack/react-store/react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], @@ -1894,7 +1959,9 @@ "get-source/data-uri-to-buffer": ["data-uri-to-buffer@2.0.2", "", {}, "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA=="], - "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="], + + "js-beautify/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], "meow/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], @@ -1910,6 +1977,8 @@ "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "path-scurry/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "postcss/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "postcss-import/resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], @@ -1944,6 +2013,8 @@ "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "sucrase/glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + "supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "tailwindcss/postcss": ["postcss@8.4.47", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.0", "source-map-js": "^1.2.1" } }, "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ=="], @@ -2034,6 +2105,30 @@ "@radix-ui/react-tooltip/@radix-ui/react-popper/@radix-ui/react-context": ["@radix-ui/react-context@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A=="], + "@sentry/bundler-plugin-core/@babel/core/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/generator": ["@babel/generator@7.26.5", "", { "dependencies": { "@babel/parser": "^7.26.5", "@babel/types": "^7.26.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.26.5", "", { "dependencies": { "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helpers": ["@babel/helpers@7.26.0", "", { "dependencies": { "@babel/template": "^7.25.9", "@babel/types": "^7.26.0" } }, "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/parser": ["@babel/parser@7.26.5", "", { "dependencies": { "@babel/types": "^7.26.5" }, "bin": "./bin/babel-parser.js" }, "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/template": ["@babel/template@7.25.9", "", { "dependencies": { "@babel/code-frame": "^7.25.9", "@babel/parser": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/traverse": ["@babel/traverse@7.26.5", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.5", "@babel/parser": "^7.26.5", "@babel/template": "^7.25.9", "@babel/types": "^7.26.5", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/types": ["@babel/types@7.26.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg=="], + + "@sentry/bundler-plugin-core/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@sentry/bundler-plugin-core/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.5.0", "", {}, "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw=="], + + "@sentry/vite-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.5.0", "", {}, "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw=="], + "@tanstack/react-store/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], @@ -2064,6 +2159,10 @@ "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "js-beautify/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "js-beautify/glob/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "next-themes/react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], "read-pkg-up/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], @@ -2074,6 +2173,10 @@ "read-pkg/normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "sucrase/glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "sucrase/glob/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "tailwindcss/postcss/nanoid": ["nanoid@3.3.7", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="], "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.23.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ=="], @@ -2228,6 +2331,24 @@ "@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="], + "@sentry/bundler-plugin-core/@babel/core/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.26.5", "", {}, "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], + + "@sentry/bundler-plugin-core/@babel/core/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + "@vitejs/plugin-react/@babel/core/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], "@vitejs/plugin-react/@babel/core/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.26.5", "", {}, "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg=="], @@ -2246,8 +2367,12 @@ "@vitejs/plugin-react/@babel/core/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], + "js-beautify/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + "sucrase/glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "vite-node/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], "vite-node/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], @@ -2346,6 +2471,8 @@ "@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], + "@sentry/bundler-plugin-core/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "@vitejs/plugin-react/@babel/core/@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], diff --git a/infra/Api.ts b/infra/Api.ts index 5c555506..d282dc64 100644 --- a/infra/Api.ts +++ b/infra/Api.ts @@ -10,8 +10,24 @@ const hono = new sst.cloudflare.Worker("Hono", { handler: "./packages/workers/src/api.ts", link: [auth, authKv, cacheKv, ...allSecrets], domain: "api." + domain, + // eventually: enable sourcemaps when this is fixed: https://github.com/sst/sst/issues/4514 + // build: { + // esbuild: { + // sourcemap: true, + // plugins: [ + // // Put the Sentry esbuild plugin after all other plugins + // sentryEsbuildPlugin({ + // authToken: process.env.SENTRY_AUTH_TOKEN, + // org: "coder-aw", + // project: "node-cloudflare-workers", + // }), + // ], + // }, + // }, transform: { worker: { + compatibilityDate: "2024-09-23", + compatibilityFlags: ["nodejs_compat"], // staging will bind to dev wrangler workers too serviceBindings: [ { diff --git a/infra/Dns.ts b/infra/Dns.ts index 67b895ab..d0125ff1 100644 --- a/infra/Dns.ts +++ b/infra/Dns.ts @@ -1,8 +1,18 @@ +import type { DomainStages } from "./types"; + +export const STAGES = { + PROD: "prod", + STG: "stg", + UAT: "uat", +} as const satisfies DomainStages; + +const BASE_DOMAIN = "semhub.dev"; + export const domain = { - prod: "semhub.dev", - stg: "stg.semhub.dev", - uat: "uat.semhub.dev", + [STAGES.PROD]: BASE_DOMAIN, + [STAGES.STG]: `stg.${BASE_DOMAIN}`, + [STAGES.UAT]: `uat.${BASE_DOMAIN}`, }[$app.stage] || $app.stage + ".stg.semhub.dev"; // export const zone = cloudflare.getZoneOutput({ diff --git a/infra/Secret.ts b/infra/Secret.ts index b561c4ed..df2613aa 100644 --- a/infra/Secret.ts +++ b/infra/Secret.ts @@ -23,6 +23,7 @@ export const secret = { githubAppClientSecret: new sst.Secret("SEMHUB_GITHUB_APP_CLIENT_SECRET"), githubAppId: new sst.Secret("SEMHUB_GITHUB_APP_ID"), githubAppPrivateKey: new sst.Secret("SEMHUB_GITHUB_APP_PRIVATE_KEY"), + sentryAuthToken: new sst.Secret("SENTRY_AUTH_TOKEN"), keys, }; diff --git a/infra/Web.ts b/infra/Web.ts index 081e476f..f8676e0f 100644 --- a/infra/Web.ts +++ b/infra/Web.ts @@ -1,10 +1,13 @@ import { apiUrl } from "./Api"; import { domain } from "./Dns"; +import { secret } from "./Secret"; const web = new sst.aws.StaticSite("Web", { path: "packages/web", environment: { // when adding new env vars, you may have to rm -rf node_modules + SENTRY_AUTH_TOKEN: secret.sentryAuthToken.value, + SST_STAGE: $app.stage, VITE_SST_STAGE: $app.stage, VITE_API_URL: apiUrl.apply((url) => { if (typeof url !== "string") { diff --git a/infra/types.ts b/infra/types.ts index d8b241cd..4fbb2352 100644 --- a/infra/types.ts +++ b/infra/types.ts @@ -3,3 +3,9 @@ export type CronPatterns = { readonly SYNC_ISSUE: "*/20 * * * *"; readonly SYNC_EMBEDDING: "0 * * * *"; }; + +export type DomainStages = { + readonly PROD: "prod"; + readonly STG: "stg"; + readonly UAT: "uat"; +}; diff --git a/packages/core/src/constants/domain.constant.ts b/packages/core/src/constants/domain.constant.ts new file mode 100644 index 00000000..4724e17b --- /dev/null +++ b/packages/core/src/constants/domain.constant.ts @@ -0,0 +1,12 @@ +import type { DomainStages } from "@/infra/types"; + +export const STAGES = { + PROD: "prod", + STG: "stg", + UAT: "uat", +} as const satisfies DomainStages; + +export const APP_DOMAIN = "semhub.dev"; +export const LOCAL_DEV_DOMAIN = `local.${APP_DOMAIN}`; +export const APP_STG_DOMAIN = `stg.${APP_DOMAIN}`; +export const APP_UAT_DOMAIN = `uat.${APP_DOMAIN}`; diff --git a/packages/core/sst-env.d.ts b/packages/core/sst-env.d.ts index 4899cdce..ce65a8a7 100644 --- a/packages/core/sst-env.d.ts +++ b/packages/core/sst-env.d.ts @@ -52,6 +52,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "SENTRY_AUTH_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } "Web": { "type": "sst.aws.StaticSite" "url": string diff --git a/packages/web/package.json b/packages/web/package.json index 2fd2643d..d1f05855 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -18,6 +18,8 @@ "@radix-ui/react-tooltip": "^1.1.4", "@semhub/core": "workspace:*", "@semhub/workers": "workspace:*", + "@sentry/react": "^8.54.0", + "@sentry/vite-plugin": "^3.1.2", "@tanstack/react-form": "^0.33.0", "@tanstack/react-query": "^5.59.6", "@tanstack/react-router": "^1.63.5", diff --git a/packages/web/src/components/search/HomepageSearch.tsx b/packages/web/src/components/search/HomepageSearch.tsx index 91456a75..b59e9a47 100644 --- a/packages/web/src/components/search/HomepageSearch.tsx +++ b/packages/web/src/components/search/HomepageSearch.tsx @@ -24,7 +24,6 @@ export function HomepageSearch() {
- {/* Suggested searches section */}
{suggestedSearches.slice(0, 4).map((search) => ( diff --git a/packages/web/src/main.tsx b/packages/web/src/main.tsx index eb09ccf5..01e98529 100644 --- a/packages/web/src/main.tsx +++ b/packages/web/src/main.tsx @@ -1,12 +1,14 @@ import "./globals.css"; import * as Counterscale from "@counterscale/tracker"; +import * as Sentry from "@sentry/react"; import { QueryClientProvider } from "@tanstack/react-query"; import { createRouter, RouterProvider } from "@tanstack/react-router"; import { Loader2Icon } from "lucide-react"; import { ThemeProvider } from "next-themes"; import ReactDOM from "react-dom/client"; +import { client } from "@/lib/api/client"; import { queryClient } from "@/lib/queryClient"; import { Error } from "./components/Error"; @@ -14,7 +16,8 @@ import { NotFound } from "./components/NotFound"; import { routeTree } from "./routeTree.gen"; const sstStage = import.meta.env.VITE_SST_STAGE; -// Initialize Counterscale analytics + +// for web analytics Counterscale.init({ siteId: `semhub-${sstStage}`, reporterUrl: "https://semhub-prod-counterscale.pages.dev/collect", @@ -35,6 +38,44 @@ const router = createRouter({ defaultErrorComponent: ({ error }) => , }); +Sentry.init({ + dsn: + sstStage === "prod" + ? "https://566d7949ee5e8265ac7d917d289585bd@o4508764596142080.ingest.us.sentry.io/4508770676637696" + : "https://bf47d2a69dccbb1f44173be530166765@o4508764596142080.ingest.us.sentry.io/4508764610494464", + environment: sstStage, + tunnel: client.sentry.tunnel.$url().toString(), + debug: sstStage === "prod" ? false : true, + integrations: [ + Sentry.tanstackRouterBrowserTracingIntegration(router), + Sentry.replayIntegration({ + // NOTE: This will disable built-in masking. Only use this if your site has no sensitive data, or if you've already set up other options for masking or blocking relevant data, such as 'ignore', 'block', 'mask' and 'maskFn'. + maskAllText: false, + blockAllMedia: false, + }), + ], + // Tracing + tracesSampleRate: sstStage === "prod" ? 0.1 : 1.0, // Capture 10% in prod, 100% elsewhere + // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled + tracePropagationTargets: [ + // uat endpoints + "https://api.uat.semhub.dev", + "https://auth.uat.semhub.dev", + // Production endpoints + "https://api.semhub.dev", + "https://auth.semhub.dev", + // stg endpoints + "https://api.stg.semhub.dev", + "https://auth.stg.semhub.dev", + // dev API endpoints with dynamic subdomains + /^https:\/\/api\.[^.]+\.stg\.semhub\.dev$/, // Matches api.{anything}.stg.semhub.dev + /^https:\/\/auth\.[^.]+\.stg\.semhub\.dev$/, // Matches auth.{anything}.stg.semhub.dev + ], + // Session Replay - only enabled in production + replaysSessionSampleRate: sstStage === "prod" ? 0.1 : 0, // 10% of sessions in prod, disabled elsewhere + replaysOnErrorSampleRate: sstStage === "prod" ? 1.0 : 0, // 100% of error sessions in prod, disabled elsewhere +}); + declare module "@tanstack/react-router" { interface Register { router: typeof router; diff --git a/packages/web/vite.config.ts b/packages/web/vite.config.ts index f6c34a0c..aa677243 100644 --- a/packages/web/vite.config.ts +++ b/packages/web/vite.config.ts @@ -1,13 +1,24 @@ import fs from "fs"; import path from "path"; +import { sentryVitePlugin } from "@sentry/vite-plugin"; import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; -// https://vitejs.dev/config/ export default defineConfig(() => { return { - plugins: [TanStackRouterVite({}), react()], + plugins: [ + TanStackRouterVite({}), + react(), + sentryVitePlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: "coder-aw", + project: + process.env.SST_STAGE === "prod" + ? "semhub-web-prod" + : "semhub-web-dev", + }), + ], resolve: { alias: { "@/core": path.resolve(__dirname, "../core/src"), @@ -16,6 +27,7 @@ export default defineConfig(() => { }, }, build: { + sourcemap: true, rollupOptions: { output: { manualChunks: { diff --git a/packages/workers/package.json b/packages/workers/package.json index 60be44ad..03b70946 100644 --- a/packages/workers/package.json +++ b/packages/workers/package.json @@ -6,10 +6,11 @@ "build": "tsc --build" }, "dependencies": { - "@semhub/core": "workspace:*", - "@semhub/wrangler": "workspace:*", "@hono/zod-validator": "^0.4.1", "@openauthjs/openauth": "*", + "@semhub/core": "workspace:*", + "@semhub/wrangler": "workspace:*", + "@sentry/cloudflare": "^8.54.0", "hono": "^4.6.5" }, "devDependencies": { diff --git a/packages/workers/src/api.ts b/packages/workers/src/api.ts index 4ccba6be..20be356a 100644 --- a/packages/workers/src/api.ts +++ b/packages/workers/src/api.ts @@ -1,5 +1,28 @@ +import type { ExportedHandler } from "@cloudflare/workers-types"; +import * as Sentry from "@sentry/cloudflare"; +import { Resource } from "sst"; + +import type { Context } from "./server/app"; import { app } from "./server/app"; -export default { - fetch: app.fetch, +type CloudflareRequest = Request>; +const handler: ExportedHandler = { + async fetch(request, env, ctx) { + // needed to fix type error + return app.fetch(request as CloudflareRequest, env, ctx); + }, }; + +// Wrap with Sentry +export default Sentry.withSentry( + () => ({ + dsn: + Resource.App.stage === "prod" + ? "https://8a5572abfbb6f99f6144edf73b98446f@o4508764596142080.ingest.us.sentry.io/4508770682273792" + : "https://d415d30f99a3f43649f2289a054fe5b2@o4508764596142080.ingest.us.sentry.io/4508764598829056", + tracesSampleRate: Resource.App.stage === "prod" ? 0.2 : 1.0, + debug: Resource.App.stage === "prod" ? false : true, + environment: Resource.App.stage, + }), + handler, +); diff --git a/packages/workers/src/auth/auth.constant.ts b/packages/workers/src/auth/auth.constant.ts index b0e477cd..d1c9afcf 100644 --- a/packages/workers/src/auth/auth.constant.ts +++ b/packages/workers/src/auth/auth.constant.ts @@ -1,7 +1,18 @@ +import { type cors } from "hono/cors"; import type { CookieOptions } from "hono/utils/cookie"; +import { + APP_DOMAIN, + APP_STG_DOMAIN, + APP_UAT_DOMAIN, + LOCAL_DEV_DOMAIN, + STAGES, +} from "@/core/constants/domain.constant"; import { GITHUB_SCOPES_PERMISSION } from "@/core/github/permission/oauth"; +// Extract CORSOptions type from cors function +type CORSOptions = NonNullable[0]>; + export const githubLogin = { provider: "github-login" as const, scopes: [ @@ -10,18 +21,13 @@ export const githubLogin = { ], }; -export const APP_DOMAIN = "semhub.dev"; -const LOCAL_DEV_DOMAIN = `local.${APP_DOMAIN}`; -const APP_STG_DOMAIN = `stg.${APP_DOMAIN}`; -const APP_UAT_DOMAIN = `uat.${APP_DOMAIN}`; - function getCookieDomain(stage: string) { switch (stage) { - case "prod": + case STAGES.PROD: return APP_DOMAIN; - case "uat": + case STAGES.UAT: return APP_UAT_DOMAIN; - case "stg": + case STAGES.STG: return APP_STG_DOMAIN; default: // For local development, we set the cookie on the parent domain (.semhub.dev) because: @@ -34,7 +40,7 @@ function getCookieDomain(stage: string) { } function isLocalDev(stage: string): boolean { - return stage !== "prod" && stage !== "stg" && stage !== "uat"; + return stage !== STAGES.PROD && stage !== STAGES.STG && stage !== STAGES.UAT; } export function getCookieOptions(stage: string): CookieOptions { @@ -55,11 +61,15 @@ export function getAuthServerCORS() { credentials: false, // can use wildcard if credentials: false is used origin: `https://*.${APP_DOMAIN}`, - allowHeaders: ["Content-Type"], + allowHeaders: [ + "Content-Type", + "sentry-trace", // Allow Sentry tracing headers + "baggage", // Allow Sentry baggage header + ], allowMethods: ["POST", "GET", "OPTIONS"], exposeHeaders: ["Content-Length", "Access-Control-Allow-Origin"], maxAge: 600, - }; + } satisfies CORSOptions; } export function getApiServerCORS(stage: string) { @@ -76,9 +86,14 @@ export function getApiServerCORS(stage: string) { return { credentials: true, origin: origins, - allowHeaders: ["Content-Type", "Authorization"], + allowHeaders: [ + "Content-Type", + "Authorization", + "sentry-trace", // Allow Sentry tracing headers + "baggage", // Allow Sentry baggage header + ], allowMethods: ["POST", "GET", "OPTIONS"], exposeHeaders: ["Content-Length", "Access-Control-Allow-Origin"], maxAge: 600, - }; + } satisfies CORSOptions; } diff --git a/packages/workers/src/auth/authenticator.ts b/packages/workers/src/auth/authenticator.ts index 9b3164ea..0a807f95 100644 --- a/packages/workers/src/auth/authenticator.ts +++ b/packages/workers/src/auth/authenticator.ts @@ -5,12 +5,13 @@ import { Hono } from "hono"; import { cors } from "hono/cors"; import { Resource } from "sst"; +import { APP_DOMAIN } from "@/core/constants/domain.constant"; import { tokensetRawSchema } from "@/core/github/schema.oauth"; import { User } from "@/core/user"; import { parseHostname } from "@/core/util/url"; import { getDeps } from "../deps"; -import { APP_DOMAIN, getAuthServerCORS, githubLogin } from "./auth.constant"; +import { getAuthServerCORS, githubLogin } from "./auth.constant"; import { subjects } from "./subjects"; const app = new Hono(); diff --git a/packages/workers/src/server/app.ts b/packages/workers/src/server/app.ts index b7e7120a..dc0e7e1f 100644 --- a/packages/workers/src/server/app.ts +++ b/packages/workers/src/server/app.ts @@ -1,3 +1,4 @@ +import * as Sentry from "@sentry/cloudflare"; import { Hono } from "hono"; import type { Env } from "hono"; import { cors } from "hono/cors"; @@ -18,6 +19,7 @@ import { authRouter } from "./router/auth.router"; import { authzRouter } from "./router/authz.router"; import { meRouter } from "./router/me/me.router"; import { publicRouter } from "./router/public/public.router"; +import { sentryRouter } from "./router/sentry.router"; import { webhookRouter } from "./router/webhook/webhook.router"; export interface Context extends Env { @@ -66,7 +68,9 @@ const _routes = app // Public routes .route("/public", publicRouter) // Webhook routes (secured by webhook secret) - .route("/webhook", webhookRouter); + .route("/webhook", webhookRouter) + // Sentry tunnel route + .route("/sentry", sentryRouter); // Export the type for client usage export type ApiRoutes = typeof _routes; @@ -82,19 +86,61 @@ app.notFound((c) => { }); app.onError((err, c) => { - if (err instanceof HTTPException) { + if (err instanceof HTTPException && err.status >= 400 && err.status < 500) { + // Don't report 4xx errors to Sentry as they are client errors return c.json( { success: false, error: err.message, - // isFormError: - // err.cause && typeof err.cause === "object" && "form" in err.cause - // ? err.cause.form === true - // : false, }, err.status, ); } + + // Add request context to Sentry + Sentry.setContext("request", { + method: c.req.method, + url: c.req.url, + headers: c.req.header(), + }); + + // Add user context if available + const user = c.get("user"); + if (user) { + Sentry.setUser({ + id: user.id, + }); + } + + // Group similar errors together using fingerprinting + Sentry.withScope((scope) => { + // Create a fingerprint based on: + // 1. Error name/type + // 2. HTTP method + // 3. Request path pattern (removing dynamic segments) + // 4. Error message (if it's a known type) + const errorType = err.name || "Error"; + const pathPattern = c.req.path.replace(/\/[0-9a-fA-F-]+/g, "/:id"); + + scope.setFingerprint([ + errorType, + c.req.method, + pathPattern, + err instanceof Error ? err.message : "Unknown Error", + ]); + + // Capture exception with extra context + Sentry.captureException(err, { + tags: { + stage: Resource.App.stage, + }, + extra: { + path: c.req.path, + query: Object.fromEntries(new URL(c.req.url).searchParams), + }, + }); + }); + const isProd = Resource.App.stage === "prod"; return c.json( { diff --git a/packages/workers/src/server/router/sentry.router.ts b/packages/workers/src/server/router/sentry.router.ts new file mode 100644 index 00000000..6a3ddfbc --- /dev/null +++ b/packages/workers/src/server/router/sentry.router.ts @@ -0,0 +1,67 @@ +import { Hono } from "hono"; +import { HTTPException } from "hono/http-exception"; + +import type { Context } from "../app"; + +export const sentryRouter = new Hono().post("/tunnel", async (c) => { + const envelopeBytes = await c.req.arrayBuffer(); + const envelope = new TextDecoder().decode(envelopeBytes); + const [headerPiece] = envelope.split("\n"); + if (!headerPiece) { + throw new HTTPException(400, { + message: "Invalid envelope: missing header", + }); + } + const header = JSON.parse(headerPiece); + if (!header.dsn) { + throw new HTTPException(400, { + message: "Invalid envelope: missing DSN", + }); + } + + // Extract Sentry details from the DSN in the envelope + const dsn = new URL(header.dsn); + const projectId = dsn.pathname.replace("/", ""); + const sentryHost = dsn.hostname; + + // Construct the upstream Sentry URL + const upstreamSentryUrl = `https://${sentryHost}/api/${projectId}/envelope/`; + + // Get the original client IP + const clientIp = + c.req.header("cf-connecting-ip") || + c.req.header("x-forwarded-for") || + c.req.header("x-real-ip"); + + // Forward the envelope to Sentry + const response = await fetch(upstreamSentryUrl, { + method: "POST", + body: envelopeBytes, + headers: { + // Forward content type + "Content-Type": + c.req.header("content-type") ?? "application/x-sentry-envelope", + // Forward client information + "User-Agent": c.req.header("user-agent") ?? "", + "X-Forwarded-For": clientIp ?? "", + // Forward other relevant headers that Sentry might use + "X-Client-IP": clientIp ?? "", + "X-Real-IP": clientIp ?? "", + // Forward geolocation data if available from Cloudflare + "CF-IPCountry": c.req.header("cf-ipcountry") ?? "", + "CF-Ray": c.req.header("cf-ray") ?? "", + }, + }); + + if (!response.ok) { + throw new HTTPException(503, { + message: "Failed to forward to Sentry", + }); + } + + // Return the response from Sentry + return new Response(response.body, { + status: response.status, + headers: response.headers, + }); +}); diff --git a/packages/workers/sst-env.d.ts b/packages/workers/sst-env.d.ts index 4899cdce..ce65a8a7 100644 --- a/packages/workers/sst-env.d.ts +++ b/packages/workers/sst-env.d.ts @@ -52,6 +52,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "SENTRY_AUTH_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } "Web": { "type": "sst.aws.StaticSite" "url": string diff --git a/packages/wrangler/sst-env.d.ts b/packages/wrangler/sst-env.d.ts index 4899cdce..ce65a8a7 100644 --- a/packages/wrangler/sst-env.d.ts +++ b/packages/wrangler/sst-env.d.ts @@ -52,6 +52,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "SENTRY_AUTH_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } "Web": { "type": "sst.aws.StaticSite" "url": string diff --git a/sst-env.d.ts b/sst-env.d.ts index bfb1bb1f..99e495b8 100644 --- a/sst-env.d.ts +++ b/sst-env.d.ts @@ -68,6 +68,10 @@ declare module "sst" { "type": "sst.sst.Secret" "value": string } + "SENTRY_AUTH_TOKEN": { + "type": "sst.sst.Secret" + "value": string + } "SyncEmbeddingHandler": { "type": "sst.cloudflare.Worker" }