diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 49e0704..21f72a5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,25 +32,12 @@ jobs: - name: Run Tests run: npm test - - name: Prepare Wrangler Config - run: | - SENTRY_DSN=$(printf '%s\n' "${{ secrets.SENTRY_DSN }}" | sed -e 's/[\/&]/\\&/g') - sed -i "s/SENTRY_DSN = \"\"/SENTRY_DSN = \"$SENTRY_DSN\"/g" wrangler.toml - - SENTRY_RELEASE=$(printf '%s\n' "${{ github.sha }}" | sed -e 's/[\/&]/\\&/g') - sed -i "s/SENTRY_RELEASE = \"\"/SENTRY_RELEASE = \"$SENTRY_RELEASE\"/g" wrangler.toml - - name: Deploy to ${{ github.ref_name }} - run: npx wrangler deploy --env ${{ github.ref_name }} --outdir dist-worker --minify + run: npx wrangler deploy --env ${{ github.ref_name }} --outdir dist-worker --minify --var SENTRY_DSN:${{ secrets.SENTRY_DSN }} --var SENTRY_RELEASE:${{ github.sha }} env: CLOUDFLARE_API_TOKEN: ${{ github.ref_name == 'production' && secrets.CLOUDFLARE_API_TOKEN_PRODUCTION || secrets.CLOUDFLARE_API_TOKEN_STAGING }} CLOUDFLARE_ACCOUNT_ID: ${{ github.ref_name == 'production' && secrets.CLOUDFLARE_ACCOUNT_ID_PRODUCTION || secrets.CLOUDFLARE_ACCOUNT_ID_STAGING }} - - name: Prepare Sentry Release - run: | - mv dist-worker/index.js dist-worker/worker.js - mv dist-worker/index.js.map dist-worker/worker.js.map - - name: Create Sentry Release uses: getsentry/action-release@dab6548b3c03c4717878099e43782cf5be654289 # v3.5.0 env: @@ -58,10 +45,10 @@ jobs: SENTRY_ORG: cdnjs SENTRY_PROJECT: api-worker with: - url_prefix: / ignore_missing: true ignore_empty: true inject: false release: ${{ github.sha }} environment: ${{ github.ref_name }} sourcemaps: dist-worker + strip_common_prefix: true diff --git a/package-lock.json b/package-lock.json index e1f79a0..a162108 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,12 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "@sentry/integrations": "^7.114.0", + "@sentry/cloudflare": "^10.38.0", "algoliasearch": "^4.22.0", "hono": "^4.11.7", "is-deflate": "^1.0.0", "is-gzip": "^2.0.0", - "pako": "^2.1.0", - "toucan-js": "^3.3.1" + "pako": "^2.1.0" }, "devDependencies": { "@babel/core": "^7.29.0", @@ -186,6 +185,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -1825,6 +1825,15 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/@paralleldrive/cuid2": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", @@ -1888,80 +1897,34 @@ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true }, - "node_modules/@sentry/core": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.76.0.tgz", - "integrity": "sha512-M+ptkCTeCNf6fn7p2MmEb1Wd9/JXUWxIT/0QEc+t11DNR4FYy1ZP2O9Zb3Zp2XacO7ORrlL3Yc+VIfl5JTgjfw==", - "dependencies": { - "@sentry/types": "7.76.0", - "@sentry/utils": "7.76.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/integrations": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.114.0.tgz", - "integrity": "sha512-BJIBWXGKeIH0ifd7goxOS29fBA8BkEgVVCahs6xIOXBjX1IRS6PmX0zYx/GP23nQTfhJiubv2XPzoYOlZZmDxg==", + "node_modules/@sentry/cloudflare": { + "version": "10.38.0", + "resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.38.0.tgz", + "integrity": "sha512-g008TNjxPbS5csEem3u6jBO40qNY4Vky5q1hJXlUjoNnCDt+5vMLPMzVqJVVbAzWWU+dwjdiMzGeNjwn0RYwcQ==", + "license": "MIT", "dependencies": { - "@sentry/core": "7.114.0", - "@sentry/types": "7.114.0", - "@sentry/utils": "7.114.0", - "localforage": "^1.8.1" + "@opentelemetry/api": "^1.9.0", + "@sentry/core": "10.38.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/integrations/node_modules/@sentry/core": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.114.0.tgz", - "integrity": "sha512-YnanVlmulkjgZiVZ9BfY9k6I082n+C+LbZo52MTvx3FY6RE5iyiPMpaOh67oXEZRWcYQEGm+bKruRxLVP6RlbA==", - "dependencies": { - "@sentry/types": "7.114.0", - "@sentry/utils": "7.114.0" + "node": ">=18" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/integrations/node_modules/@sentry/types": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.114.0.tgz", - "integrity": "sha512-tsqkkyL3eJtptmPtT0m9W/bPLkU7ILY7nvwpi1hahA5jrM7ppoU0IMaQWAgTD+U3rzFH40IdXNBFb8Gnqcva4w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/integrations/node_modules/@sentry/utils": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.114.0.tgz", - "integrity": "sha512-319N90McVpupQ6vws4+tfCy/03AdtsU0MurIE4+W5cubHME08HtiEWlfacvAxX+yuKFhvdsO4K4BB/dj54ideg==", - "dependencies": { - "@sentry/types": "7.114.0" + "peerDependencies": { + "@cloudflare/workers-types": "^4.x" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/types": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.76.0.tgz", - "integrity": "sha512-vj6z+EAbVrKAXmJPxSv/clpwS9QjPqzkraMFk2hIdE/kii8s8kwnkBwTSpIrNc8GnzV3qYC4r3qD+BXDxAGPaw==", - "engines": { - "node": ">=8" + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } } }, - "node_modules/@sentry/utils": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.76.0.tgz", - "integrity": "sha512-40jFD+yfQaKpFYINghdhovzec4IEpB7aAuyH/GtE7E0gLpcqnC72r55krEIVILfqIR2Mlr5OKUzyeoCyWAU/yw==", - "dependencies": { - "@sentry/types": "7.76.0" - }, + "node_modules/@sentry/core": { + "version": "10.38.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.38.0.tgz", + "integrity": "sha512-1pubWDZE5y5HZEPMAZERP4fVl2NH3Ihp1A+vMoVkb3Qc66Diqj1WierAnStlZP7tCx0TBa0dK85GTW/ZFYyB9g==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" } }, "node_modules/@sindresorhus/base62": { @@ -2063,6 +2026,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2369,6 +2333,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3187,6 +3152,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4132,11 +4098,6 @@ "node": ">= 4" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -4763,14 +4724,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", - "dependencies": { - "immediate": "~3.0.5" - } - }, "node_modules/lintspaces": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/lintspaces/-/lintspaces-0.6.3.tgz", @@ -4785,14 +4738,6 @@ "node": ">=5" } }, - "node_modules/localforage": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", - "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", - "dependencies": { - "lie": "3.1.1" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -6287,31 +6232,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/toucan-js": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/toucan-js/-/toucan-js-3.3.1.tgz", - "integrity": "sha512-9BpkHb/Pzsrtl1ItNq9OEQPnuUHwzce0nV2uG+DYFiQ4fPyiA6mKTBcDwQzcvNkfSER038U+8TzvdkCev+Maww==", - "dependencies": { - "@sentry/core": "7.76.0", - "@sentry/integrations": "7.76.0", - "@sentry/types": "7.76.0", - "@sentry/utils": "7.76.0" - } - }, - "node_modules/toucan-js/node_modules/@sentry/integrations": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.76.0.tgz", - "integrity": "sha512-4ea0PNZrGN9wKuE/8bBCRrxxw4Cq5T710y8rhdKHAlSUpbLqr/atRF53h8qH3Fi+ec0m38PB+MivKem9zUwlwA==", - "dependencies": { - "@sentry/core": "7.76.0", - "@sentry/types": "7.76.0", - "@sentry/utils": "7.76.0", - "localforage": "^1.8.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -6468,6 +6388,7 @@ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", "dev": true, + "peer": true, "dependencies": { "pathe": "^2.0.3" } @@ -6617,6 +6538,7 @@ "integrity": "sha512-EhLJGptSGFi8AEErLiamO3PoGpbRqL+v4Ve36H2B38VxmDgFOSmDhfepBnA14sCQzGf1AEaoZX2DCwZsmO74yQ==", "dev": true, "hasInstallScript": true, + "peer": true, "bin": { "workerd": "bin/workerd" }, @@ -7061,6 +6983,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, + "peer": true, "requires": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -7991,6 +7914,11 @@ "fastq": "^1.6.0" } }, + "@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" + }, "@paralleldrive/cuid2": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", @@ -8047,62 +7975,19 @@ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true }, - "@sentry/core": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.76.0.tgz", - "integrity": "sha512-M+ptkCTeCNf6fn7p2MmEb1Wd9/JXUWxIT/0QEc+t11DNR4FYy1ZP2O9Zb3Zp2XacO7ORrlL3Yc+VIfl5JTgjfw==", + "@sentry/cloudflare": { + "version": "10.38.0", + "resolved": "https://registry.npmjs.org/@sentry/cloudflare/-/cloudflare-10.38.0.tgz", + "integrity": "sha512-g008TNjxPbS5csEem3u6jBO40qNY4Vky5q1hJXlUjoNnCDt+5vMLPMzVqJVVbAzWWU+dwjdiMzGeNjwn0RYwcQ==", "requires": { - "@sentry/types": "7.76.0", - "@sentry/utils": "7.76.0" + "@opentelemetry/api": "^1.9.0", + "@sentry/core": "10.38.0" } }, - "@sentry/integrations": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.114.0.tgz", - "integrity": "sha512-BJIBWXGKeIH0ifd7goxOS29fBA8BkEgVVCahs6xIOXBjX1IRS6PmX0zYx/GP23nQTfhJiubv2XPzoYOlZZmDxg==", - "requires": { - "@sentry/core": "7.114.0", - "@sentry/types": "7.114.0", - "@sentry/utils": "7.114.0", - "localforage": "^1.8.1" - }, - "dependencies": { - "@sentry/core": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.114.0.tgz", - "integrity": "sha512-YnanVlmulkjgZiVZ9BfY9k6I082n+C+LbZo52MTvx3FY6RE5iyiPMpaOh67oXEZRWcYQEGm+bKruRxLVP6RlbA==", - "requires": { - "@sentry/types": "7.114.0", - "@sentry/utils": "7.114.0" - } - }, - "@sentry/types": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.114.0.tgz", - "integrity": "sha512-tsqkkyL3eJtptmPtT0m9W/bPLkU7ILY7nvwpi1hahA5jrM7ppoU0IMaQWAgTD+U3rzFH40IdXNBFb8Gnqcva4w==" - }, - "@sentry/utils": { - "version": "7.114.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.114.0.tgz", - "integrity": "sha512-319N90McVpupQ6vws4+tfCy/03AdtsU0MurIE4+W5cubHME08HtiEWlfacvAxX+yuKFhvdsO4K4BB/dj54ideg==", - "requires": { - "@sentry/types": "7.114.0" - } - } - } - }, - "@sentry/types": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.76.0.tgz", - "integrity": "sha512-vj6z+EAbVrKAXmJPxSv/clpwS9QjPqzkraMFk2hIdE/kii8s8kwnkBwTSpIrNc8GnzV3qYC4r3qD+BXDxAGPaw==" - }, - "@sentry/utils": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.76.0.tgz", - "integrity": "sha512-40jFD+yfQaKpFYINghdhovzec4IEpB7aAuyH/GtE7E0gLpcqnC72r55krEIVILfqIR2Mlr5OKUzyeoCyWAU/yw==", - "requires": { - "@sentry/types": "7.76.0" - } + "@sentry/core": { + "version": "10.38.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.38.0.tgz", + "integrity": "sha512-1pubWDZE5y5HZEPMAZERP4fVl2NH3Ihp1A+vMoVkb3Qc66Diqj1WierAnStlZP7tCx0TBa0dK85GTW/ZFYyB9g==" }, "@sindresorhus/base62": { "version": "1.0.0", @@ -8183,7 +8068,8 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true + "dev": true, + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -8404,6 +8290,7 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, + "peer": true, "requires": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -8990,6 +8877,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, + "peer": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -9655,11 +9543,6 @@ "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -10071,14 +9954,6 @@ "type-check": "~0.4.0" } }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", - "requires": { - "immediate": "~3.0.5" - } - }, "lintspaces": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/lintspaces/-/lintspaces-0.6.3.tgz", @@ -10090,14 +9965,6 @@ "rc": "^1.2.8" } }, - "localforage": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", - "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", - "requires": { - "lie": "3.1.1" - } - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -11149,30 +11016,6 @@ "reserved-identifiers": "^1.0.0" } }, - "toucan-js": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/toucan-js/-/toucan-js-3.3.1.tgz", - "integrity": "sha512-9BpkHb/Pzsrtl1ItNq9OEQPnuUHwzce0nV2uG+DYFiQ4fPyiA6mKTBcDwQzcvNkfSER038U+8TzvdkCev+Maww==", - "requires": { - "@sentry/core": "7.76.0", - "@sentry/integrations": "7.76.0", - "@sentry/types": "7.76.0", - "@sentry/utils": "7.76.0" - }, - "dependencies": { - "@sentry/integrations": { - "version": "7.76.0", - "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.76.0.tgz", - "integrity": "sha512-4ea0PNZrGN9wKuE/8bBCRrxxw4Cq5T710y8rhdKHAlSUpbLqr/atRF53h8qH3Fi+ec0m38PB+MivKem9zUwlwA==", - "requires": { - "@sentry/core": "7.76.0", - "@sentry/types": "7.76.0", - "@sentry/utils": "7.76.0", - "localforage": "^1.8.1" - } - } - } - }, "tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -11289,6 +11132,7 @@ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", "dev": true, + "peer": true, "requires": { "pathe": "^2.0.3" } @@ -11387,6 +11231,7 @@ "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260128.0.tgz", "integrity": "sha512-EhLJGptSGFi8AEErLiamO3PoGpbRqL+v4Ve36H2B38VxmDgFOSmDhfepBnA14sCQzGf1AEaoZX2DCwZsmO74yQ==", "dev": true, + "peer": true, "requires": { "@cloudflare/workerd-darwin-64": "1.20260128.0", "@cloudflare/workerd-darwin-arm64": "1.20260128.0", diff --git a/package.json b/package.json index a9ffe8e..3a6afcf 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,12 @@ "node": ">=24.11.0" }, "dependencies": { - "@sentry/integrations": "^7.114.0", + "@sentry/cloudflare": "^10.38.0", "algoliasearch": "^4.22.0", "hono": "^4.11.7", "is-deflate": "^1.0.0", "is-gzip": "^2.0.0", - "pako": "^2.1.0", - "toucan-js": "^3.3.1" + "pako": "^2.1.0" }, "devDependencies": { "@babel/core": "^7.29.0", diff --git a/src/index.js b/src/index.js index b15e65a..6cfaaf4 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,7 @@ -import { RewriteFrames } from '@sentry/integrations'; -import { env } from 'cloudflare:workers'; +import * as Sentry from '@sentry/cloudflare'; import { Hono } from 'hono'; import { cors } from 'hono/cors'; import { logger } from 'hono/logger'; -import { Toucan, RequestData } from 'toucan-js'; import errorRoutes from './routes/errors.js'; import indexRoutes from './routes/index.js'; @@ -18,55 +16,6 @@ const app = new Hono(); app.use('*', logger()); app.use('*', cors(corsOptions)); -// Inject Sentry -if (env.SENTRY_DSN) { - app.use('*', async (ctx, next) => { - // Create the Sentry instance - ctx.sentry = new Toucan({ - dsn: env.SENTRY_DSN, - context: { - waitUntil: ctx.executionCtx.waitUntil.bind(ctx.executionCtx), - request: ctx.req, - }, - integrations: [ - new RequestData({ - allowedHeaders: [ 'user-agent', 'cf-ray' ], - allowedSearchParams: /(.*)/, - }), - new RewriteFrames({ - /** - * @template {{ filename: string }} T - * - * Rewrite error stack frames to fix the source file path. - * - * @param {T} frame Stack frame to fix. - * @return {T} - */ - iteratee: frame => { - // Root should be `/` - frame.filename = frame.filename.replace(/^(async )?worker\.js/, '/worker.js'); - return frame; - }, - }), - ], - release: env.SENTRY_RELEASE || undefined, - environment: env.SENTRY_ENVIRONMENT || undefined, - }); - - // Track the colo we're in - const colo = ctx.req.raw.cf?.colo || 'UNKNOWN'; - ctx.sentry.setTag('colo', colo); - - // Track the connecting user - const ipAddress = ctx.req.header('cf-connecting-ip') || ctx.req.header('x-forwarded-for') || undefined; - const userAgent = ctx.req.header('user-agent') || undefined; - ctx.sentry.setUser({ ip: ipAddress, userAgent, colo }); - - // Continue - await next(); - }); -} - // Load the routes indexRoutes(app); statsRoutes(app); @@ -76,4 +25,8 @@ librariesRoutes(app); errorRoutes(app); // Let's go! -export default app; +export default Sentry.withSentry(env => ({ + dsn: env.SENTRY_DSN, + release: env.SENTRY_RELEASE, + environment: env.SENTRY_ENVIRONMENT, +}), app); diff --git a/src/routes/errors.js b/src/routes/errors.js index add65f9..f7f4835 100644 --- a/src/routes/errors.js +++ b/src/routes/errors.js @@ -1,3 +1,5 @@ +import * as Sentry from '@sentry/cloudflare'; + import cache from '../utils/cache.js'; import notFound from '../utils/notFound.js'; import respond from '../utils/respond.js'; @@ -8,6 +10,25 @@ import respond from '../utils/respond.js'; * @param {import('hono').Hono} app App instance. */ export default app => { + // Pass request context to Sentry + app.use('*', async (ctx, next) => { + Sentry.setTags({ + requestId: crypto.randomUUID(), + userAgent: ctx.req.header('user-agent'), + ray: ctx.req.header('cf-ray'), + country: ctx.req.raw.cf?.country, + colo: ctx.req.raw.cf?.colo, + }); + + Sentry.setUser({ + ip: ctx.req.header('cf-connecting-ip') || ctx.req.header('x-forwarded-for'), + userAgent: ctx.req.header('user-agent'), + colo: ctx.req.raw.cf?.colo, + }); + + await next(); + }); + // Handle 404s app.notFound(ctx => notFound(ctx, 'Endpoint')); @@ -21,7 +42,7 @@ export default app => { app.onError((err, ctx) => { // Log the error console.error(err.stack); - const sentry = ctx.sentry?.captureException(err); + const sentry = Sentry.captureException(err); // Never cache this cache(ctx, -1); diff --git a/src/routes/libraries.js b/src/routes/libraries.js index 747c528..d44fa7a 100644 --- a/src/routes/libraries.js +++ b/src/routes/libraries.js @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/cloudflare'; import { env } from 'cloudflare:workers'; import algolia from '../utils/algolia.js'; @@ -92,9 +93,9 @@ const handleGetLibraries = async ctx => { if (hit?.name) return true; console.warn('Found bad entry in Algolia data'); console.info(hit); - ctx.sentry?.withScope(scope => { + Sentry.withScope(scope => { scope.setExtra('hit', hit); - ctx.sentry.captureException(new Error('Bad entry in Algolia data')); + Sentry.captureException(new Error('Bad entry in Algolia data')); }); return false; }).map(hit => filter( diff --git a/src/routes/library.js b/src/routes/library.js index fffa4db..80e05ac 100644 --- a/src/routes/library.js +++ b/src/routes/library.js @@ -25,7 +25,7 @@ const whitelisted = file => extensions.includes(file.split('.').slice(-1)[0]); */ const handleGetLibraryVersion = async ctx => { // Get the library - const lib = await library(ctx.req.param('library'), ctx.sentry).catch(err => { + const lib = await library(ctx.req.param('library')).catch(err => { if (err.status === 404) return; throw err; }); @@ -60,7 +60,7 @@ const handleGetLibraryVersion = async ctx => { if ('sri' in response) { // Get SRI for version const latestSriData = await libraryVersionSri(lib.name, ctx.req.param('version')).catch(() => {}); - response.sri = sriForVersion(lib.name, ctx.req.param('version'), version, latestSriData, ctx.sentry); + response.sri = sriForVersion(lib.name, ctx.req.param('version'), version, latestSriData); } // Set a 355 day (same as CDN) life on this response @@ -79,7 +79,7 @@ const handleGetLibraryVersion = async ctx => { */ const handleGetLibrary = async ctx => { // Get the library - const lib = await library(ctx.req.param('library'), ctx.sentry).catch(err => { + const lib = await library(ctx.req.param('library')).catch(err => { if (err.status === 404) return; throw err; }); @@ -123,7 +123,7 @@ const handleGetLibrary = async ctx => { version: lib.version, files: assets.filter(whitelisted), rawFiles: assets, - sri: sriForVersion(lib.name, lib.version, assets, sriData, ctx.sentry), + sri: sriForVersion(lib.name, lib.version, assets, sriData), } ]; } } @@ -150,7 +150,6 @@ const handleGetLibrary = async ctx => { lib.version, [ lib.filename ], latestSriData, - ctx.sentry, )[lib.filename] || null; } } diff --git a/src/utils/kvMetadata.js b/src/utils/kvMetadata.js index 1b6998f..62ed194 100644 --- a/src/utils/kvMetadata.js +++ b/src/utils/kvMetadata.js @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/cloudflare'; import { env } from 'cloudflare:workers'; import fetchJson from './fetchJson.js'; @@ -18,10 +19,9 @@ export const libraries = () => fetchJson(`${kvBase}/packages`); * * @param {string} library Requested library name. * @param {T} data Returned library data to validate. - * @param {import('toucan-js')} [sentry] Sentry instance for missing version reporting. * @return {T & { assets: [] }} */ -const kvLibraryValidate = (library, data, sentry = undefined) => { +const kvLibraryValidate = (library, data) => { // Assets might not exist if there are none, but we should make it an empty array by default data.assets = data.assets || []; @@ -34,9 +34,9 @@ const kvLibraryValidate = (library, data, sentry = undefined) => { // Breaking issues if (!data.version) { console.error('Version missing', data.name, data); - sentry?.withScope(scope => { + Sentry.withScope(scope => { scope.setExtra('data', data); - sentry.captureException(new Error('Version missing in package data')); + Sentry.captureException(new Error('Version missing in package data')); }); throw new Error('Version missing in package data'); } @@ -48,11 +48,10 @@ const kvLibraryValidate = (library, data, sentry = undefined) => { * Get the metadata for a library. * * @param {string} name Name of the library to fetch. - * @param {import('toucan-js')} [sentry] Sentry instance for data validation reporting. * @return {Promise} */ -export const library = (name, sentry = undefined) => fetchJson(`${kvBase}/packages/${encodeURIComponent(name)}`) - .then(data => kvLibraryValidate(name, data, sentry)); +export const library = name => fetchJson(`${kvBase}/packages/${encodeURIComponent(name)}`) + .then(data => kvLibraryValidate(name, data)); /** * Get the versions for a library. diff --git a/src/utils/spec/request.js b/src/utils/spec/request.js index 1b72a28..f15974d 100644 --- a/src/utils/spec/request.js +++ b/src/utils/spec/request.js @@ -26,6 +26,7 @@ export default async (route, opts = {}, preHook = undefined, postHook = undefine if (!mf) { mf = new Miniflare({ modules: [ { type: 'ESModule', path: fileURLToPath(new URL('../../../dist-worker/index.js', import.meta.url)) } ], + compatibilityFlags: [ 'nodejs_als' ], kvNamespaces: [ 'CACHE' ], bindings: { DISABLE_CACHING: false, diff --git a/src/utils/sriForVersion.js b/src/utils/sriForVersion.js index c2174e2..f6598f4 100644 --- a/src/utils/sriForVersion.js +++ b/src/utils/sriForVersion.js @@ -1,3 +1,5 @@ +// import * as Sentry from '@sentry/cloudflare'; + /** * Create a map of file names to SRI hashes, based on library files and SRI data. * @@ -5,10 +7,9 @@ * @param {string} version Version of the library. * @param {string[]} files Names of the files for this version of the library. * @param {Object} sriData SRI data for the libary version. - * @param {import('toucan-js')} [_sentry] Sentry instance for missing SRI reporting. * @return {Object} */ -export default (library, version, files, sriData, _sentry = undefined) => { +export default (library, version, files, sriData) => { // Build the SRI object const sri = {}; for (const file of files) { @@ -23,12 +24,12 @@ export default (library, version, files, sriData, _sentry = undefined) => { // If we don't have an SRI entry, but expect one, error! if (file.endsWith('.js') || file.endsWith('.css')) { console.warn('Missing SRI entry for', fullFile); - // sentry?.withScope(scope => { + // Sentry.withScope(scope => { // scope.setTag('library', library); // scope.setTag('library.version', version); // scope.setTag('library.file', file); // scope.setTag('library.file.full', fullFile); - // sentry.captureException(new Error('Missing SRI entry')); + // Sentry.captureException(new Error('Missing SRI entry')); // }); } } diff --git a/wrangler.toml b/wrangler.toml index 1ddac5e..caeacc2 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,6 +1,7 @@ name = "cdnjs-api-worker" main = "src/index.js" compatibility_date = "2022-05-20" +compatibility_flags = [ "nodejs_als" ] kv_namespaces = [ { binding = "CACHE", id = "845ae1599dcf4d75950b61201a951b73", preview_id = "845ae1599dcf4d75950b61201a951b73" } ]