diff --git a/apps/proxy/package.json b/apps/proxy/package.json index 84f70924e..15ed6ae0e 100644 --- a/apps/proxy/package.json +++ b/apps/proxy/package.json @@ -7,9 +7,9 @@ "dev": "wrangler dev" }, "devDependencies": { - "@cloudflare/workers-types": "^4.20230419.0", + "@cloudflare/workers-types": "^4.20240512.0", "typescript": "^5.0.4", - "wrangler": "^3.0.0" + "wrangler": "^3.57.1" }, "dependencies": { "@aws-sdk/client-sqs": "^3.445.0", diff --git a/apps/proxy/src/index.ts b/apps/proxy/src/index.ts index b6db2f60f..e8cf12892 100644 --- a/apps/proxy/src/index.ts +++ b/apps/proxy/src/index.ts @@ -1,5 +1,7 @@ import { queueEvent } from "./events/queueEvent"; import { queueEvents } from "./events/queueEvents"; +import { applyRateLimit } from "./rateLimit"; +import { Ratelimit } from "./rateLimiter"; export interface Env { /** The hostname needs to be changed to allow requests to pass to the Trigger.dev platform */ @@ -9,6 +11,8 @@ export interface Env { AWS_SQS_SECRET_ACCESS_KEY: string; AWS_SQS_QUEUE_URL: string; AWS_SQS_REGION: string; + //rate limiter + API_RATE_LIMITER: Ratelimit; } export default { @@ -25,13 +29,13 @@ export default { switch (url.pathname) { case "/api/v1/events": { if (request.method === "POST") { - return queueEvent(request, env); + return applyRateLimit(request, env, () => queueEvent(request, env)); } break; } case "/api/v1/events/bulk": { if (request.method === "POST") { - return queueEvents(request, env); + return applyRateLimit(request, env, () => queueEvents(request, env)); } break; } diff --git a/apps/proxy/src/rateLimit.ts b/apps/proxy/src/rateLimit.ts new file mode 100644 index 000000000..ccbd7b433 --- /dev/null +++ b/apps/proxy/src/rateLimit.ts @@ -0,0 +1,46 @@ +import { Env } from "src"; +import { getApiKeyFromRequest } from "./apikey"; +import { json } from "./json"; + +export async function applyRateLimit( + request: Request, + env: Env, + fn: () => Promise +): Promise { + const apiKey = getApiKeyFromRequest(request); + if (apiKey) { + const result = await env.API_RATE_LIMITER.limit({ key: `apikey-${apiKey.apiKey}` }); + const { success } = result; + console.log(`Rate limiter`, { + success, + key: `${apiKey.apiKey.substring(0, 12)}...`, + }); + if (!success) { + //60s in the future + const reset = Date.now() + 60 * 1000; + const secondsUntilReset = Math.max(0, (reset - new Date().getTime()) / 1000); + + return json( + { + title: "Rate Limit Exceeded", + status: 429, + type: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429", + detail: `Rate limit exceeded. Retry in ${secondsUntilReset} seconds.`, + error: `Rate limit exceeded. Retry in ${secondsUntilReset} seconds.`, + reset, + }, + { + status: 429, + headers: { + "x-ratelimit-reset": reset.toString(), + }, + } + ); + } + } else { + console.log(`Rate limiter: no API key for request`); + } + + //call the original function + return fn(); +} diff --git a/apps/proxy/src/rateLimiter.ts b/apps/proxy/src/rateLimiter.ts new file mode 100644 index 000000000..414332343 --- /dev/null +++ b/apps/proxy/src/rateLimiter.ts @@ -0,0 +1,23 @@ +export interface Ratelimit { + /* + * The ratelimit function + * @param {RatelimitOptions} options + * @returns {Promise} + */ + limit: (options: RatelimitOptions) => Promise; +} + +export interface RatelimitOptions { + /* + * The key to identify the user, can be an IP address, user ID, etc. + */ + key: string; +} + +export interface RatelimitResponse { + /* + * The ratelimit success status + * @returns {boolean} + */ + success: boolean; +} diff --git a/apps/proxy/wrangler.toml b/apps/proxy/wrangler.toml index 930f0de83..3cbfb66cd 100644 --- a/apps/proxy/wrangler.toml +++ b/apps/proxy/wrangler.toml @@ -1,7 +1,33 @@ name = "proxy" main = "src/index.ts" -compatibility_date = "2023-10-30" +compatibility_date = "2024-05-13" compatibility_flags = [ "nodejs_compat" ] [env.staging] -[env.prod] \ No newline at end of file + # The rate limiting API is in open beta. + [[env.staging.unsafe.bindings]] + name = "API_RATE_LIMITER" + type = "ratelimit" + # An identifier you define, that is unique to your Cloudflare account. + # Must be an integer. + namespace_id = "1" + + # Limit: the number of tokens allowed within a given period in a single + # Cloudflare location + # Period: the duration of the period, in seconds. Must be either 10 or 60 + simple = { limit = 100, period = 60 } + + +[env.prod] + # The rate limiting API is in open beta. + [[env.prod.unsafe.bindings]] + name = "API_RATE_LIMITER" + type = "ratelimit" + # An identifier you define, that is unique to your Cloudflare account. + # Must be an integer. + namespace_id = "2" + + # Limit: the number of tokens allowed within a given period in a single + # Cloudflare location + # Period: the duration of the period, in seconds. Must be either 10 or 60 + simple = { limit = 300, period = 60 } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f99275a30..34fffc59e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -190,14 +190,14 @@ importers: version: 1.5.0 devDependencies: '@cloudflare/workers-types': - specifier: ^4.20230419.0 - version: 4.20231121.0 + specifier: ^4.20240512.0 + version: 4.20240512.0 typescript: specifier: ^5.0.4 version: 5.2.2 wrangler: - specifier: ^3.0.0 - version: 3.17.1 + specifier: ^3.57.1 + version: 3.57.1(@cloudflare/workers-types@4.20240512.0) apps/webapp: dependencies: @@ -5610,6 +5610,13 @@ packages: mime: 3.0.0 dev: true + /@cloudflare/kv-asset-handler@0.3.2: + resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==} + engines: {node: '>=16.13'} + dependencies: + mime: 3.0.0 + dev: true + /@cloudflare/workerd-darwin-64@1.20231030.0: resolution: {integrity: sha512-J4PQ9utPxLya9yHdMMx3AZeC5M/6FxcoYw6jo9jbDDFTy+a4Gslqf4Im9We3aeOEdPXa3tgQHVQOSelJSZLhIw==} engines: {node: '>=16'} @@ -5619,6 +5626,15 @@ packages: dev: true optional: true + /@cloudflare/workerd-darwin-64@1.20240512.0: + resolution: {integrity: sha512-VMp+CsSHFALQiBzPdQ5dDI4T1qwLu0mQ0aeKVNDosXjueN0f3zj/lf+mFil5/9jBbG3t4mG0y+6MMnalP9Lobw==} + engines: {node: '>=16'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@cloudflare/workerd-darwin-arm64@1.20231030.0: resolution: {integrity: sha512-WSJJjm11Del4hSneiNB7wTXGtBXI4QMCH9l5qf4iT5PAW8cESGcCmdHtWDWDtGAAGcvmLT04KNvmum92vRKKQQ==} engines: {node: '>=16'} @@ -5628,6 +5644,15 @@ packages: dev: true optional: true + /@cloudflare/workerd-darwin-arm64@1.20240512.0: + resolution: {integrity: sha512-lZktXGmzMrB5rJqY9+PmnNfv1HKlj/YLZwMjPfF0WVKHUFdvQbAHsi7NlKv6mW9uIvlZnS+K4sIkWc0MDXcRnA==} + engines: {node: '>=16'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@cloudflare/workerd-linux-64@1.20231030.0: resolution: {integrity: sha512-2HUeRTvoCC17fxE0qdBeR7J9dO8j4A8ZbdcvY8pZxdk+zERU6+N03RTbk/dQMU488PwiDvcC3zZqS4gwLfVT8g==} engines: {node: '>=16'} @@ -5637,6 +5662,15 @@ packages: dev: true optional: true + /@cloudflare/workerd-linux-64@1.20240512.0: + resolution: {integrity: sha512-wrHvqCZZqXz6Y3MUTn/9pQNsvaoNjbJpuA6vcXsXu8iCzJi911iVW2WUEBX+MpUWD+mBIP0oXni5tTlhkokOPw==} + engines: {node: '>=16'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@cloudflare/workerd-linux-arm64@1.20231030.0: resolution: {integrity: sha512-4/GK5zHh+9JbUI6Z5xTCM0ZmpKKHk7vu9thmHjUxtz+o8Ne9DoD7DlDvXQWgMF6XGaTubDWyp3ttn+Qv8jDFuQ==} engines: {node: '>=16'} @@ -5646,6 +5680,15 @@ packages: dev: true optional: true + /@cloudflare/workerd-linux-arm64@1.20240512.0: + resolution: {integrity: sha512-YPezHMySL9J9tFdzxz390eBswQ//QJNYcZolz9Dgvb3FEfdpK345cE/bsWbMOqw5ws2f82l388epoenghtYvAg==} + engines: {node: '>=16'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@cloudflare/workerd-windows-64@1.20231030.0: resolution: {integrity: sha512-fb/Jgj8Yqy3PO1jLhk7mTrHMkR8jklpbQFud6rL/aMAn5d6MQbaSrYOCjzkKGp0Zng8D2LIzSl+Fc0C9Sggxjg==} engines: {node: '>=16'} @@ -5655,10 +5698,23 @@ packages: dev: true optional: true + /@cloudflare/workerd-windows-64@1.20240512.0: + resolution: {integrity: sha512-SxKapDrIYSscMR7lGIp/av0l6vokjH4xQ9ACxHgXh+OdOus9azppSmjaPyw4/ePvg7yqpkaNjf9o258IxWtvKQ==} + engines: {node: '>=16'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@cloudflare/workers-types@4.20231121.0: resolution: {integrity: sha512-+kWfpCkqiepwAKXyHoE0gnkPgkLhz0/9HOBIGhHRsUvUKvhUtm3mbqqoGRWgF1qcjzrDUBbrrOq4MYHfFtc2RA==} dev: true + /@cloudflare/workers-types@4.20240512.0: + resolution: {integrity: sha512-o2yTEWg+YK/I1t/Me+dA0oarO0aCbjibp6wSeaw52DSE9tDyKJ7S+Qdyw/XsMrKn4t8kF6f/YOba+9O4MJfW9w==} + dev: true + /@codemirror/autocomplete@6.4.0(@codemirror/language@6.3.2)(@codemirror/state@6.2.0)(@codemirror/view@6.7.2)(@lezer/common@1.0.2): resolution: {integrity: sha512-HLF2PnZAm1s4kGs30EiqKMgD7XsYaQ0XJnMR0rofEWQ5t5D60SfqpDIkIh1ze5tiEbyUWm8+VJ6W1/erVvBMIA==} peerDependencies: @@ -13730,7 +13786,7 @@ packages: eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.45.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.6)(eslint@8.45.0) eslint-plugin-jest: 26.9.0(@typescript-eslint/eslint-plugin@5.59.6)(eslint@8.45.0)(typescript@4.9.5) eslint-plugin-jest-dom: 4.0.3(eslint@8.45.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.45.0) @@ -16424,6 +16480,7 @@ packages: typescript: 4.9.5 transitivePeerDependencies: - supports-color + dev: true /@typescript-eslint/parser@5.59.6(eslint@8.45.0)(typescript@5.1.6): resolution: {integrity: sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==} @@ -16443,7 +16500,6 @@ packages: typescript: 5.1.6 transitivePeerDependencies: - supports-color - dev: false /@typescript-eslint/parser@5.59.6(eslint@8.45.0)(typescript@5.2.2): resolution: {integrity: sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==} @@ -16609,6 +16665,7 @@ packages: typescript: 4.9.5 transitivePeerDependencies: - supports-color + dev: true /@typescript-eslint/typescript-estree@5.59.6(typescript@5.0.4): resolution: {integrity: sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==} @@ -16650,7 +16707,6 @@ packages: typescript: 5.1.6 transitivePeerDependencies: - supports-color - dev: false /@typescript-eslint/typescript-estree@5.59.6(typescript@5.2.2): resolution: {integrity: sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==} @@ -20991,7 +21047,7 @@ packages: eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-node@0.3.7)(eslint-plugin-import@2.27.5)(eslint@8.45.0) - eslint-plugin-import: 2.27.5(eslint@8.45.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.45.0) eslint-plugin-react: 7.32.2(eslint@8.45.0) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.45.0) @@ -21281,7 +21337,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.59.6(eslint@8.45.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.59.6(eslint@8.45.0)(typescript@5.1.6) debug: 3.2.7(supports-color@5.5.0) eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 @@ -21289,6 +21345,35 @@ packages: transitivePeerDependencies: - supports-color + /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0): + resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.59.6(eslint@8.45.0)(typescript@4.9.5) + debug: 3.2.7(supports-color@5.5.0) + eslint: 8.45.0 + eslint-import-resolver-node: 0.3.7 + transitivePeerDependencies: + - supports-color + dev: true + /eslint-plugin-es@3.0.1(eslint@8.31.0): resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} @@ -21398,7 +21483,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.59.6(eslint@8.45.0)(typescript@4.9.5) + '@typescript-eslint/parser': 5.59.6(eslint@8.45.0)(typescript@5.1.6) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -21420,7 +21505,7 @@ packages: - eslint-import-resolver-webpack - supports-color - /eslint-plugin-import@2.27.5(eslint@8.45.0): + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.59.6)(eslint@8.45.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -21430,6 +21515,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: + '@typescript-eslint/parser': 5.59.6(eslint@8.45.0)(typescript@4.9.5) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 @@ -21437,7 +21523,7 @@ packages: doctrine: 2.1.0 eslint: 8.45.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.45.0) + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.59.6)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0) has: 1.0.3 is-core-module: 2.13.0 is-glob: 4.0.3 @@ -21450,7 +21536,7 @@ packages: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - dev: false + dev: true /eslint-plugin-jest-dom@4.0.3(eslint@8.31.0): resolution: {integrity: sha512-9j+n8uj0+V0tmsoS7bYC7fLhQmIvjRqRYEcbDSi+TKPsTThLLXCyj5swMSSf/hTleeMktACnn+HFqXBr5gbcbA==} @@ -26964,29 +27050,6 @@ packages: hasBin: true dev: true - /miniflare@3.20231030.1: - resolution: {integrity: sha512-Y+EkgV/aFg/3Y/xfFtImK36sLZGXvNS45avVEz0cUCA2pGpg4hGdPu1Udmz5b06SyeUEFVf/dEDMJwdRYVEgLw==} - engines: {node: '>=16.13'} - hasBin: true - dependencies: - acorn: 8.10.0 - acorn-walk: 8.3.2 - capnp-ts: 0.7.0 - exit-hook: 2.2.1 - glob-to-regexp: 0.4.1 - source-map-support: 0.5.21 - stoppable: 1.1.0 - undici: 5.25.4 - workerd: 1.20231030.0 - ws: 8.16.0 - youch: 3.3.3 - zod: 3.22.4 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - /miniflare@3.20231030.2: resolution: {integrity: sha512-+DYdMqWlUaY4wBylIjewNu8OVsPFquYjQkxoSb2jGIMBmlKaef65Hn2Bu8sub5tQzQ8tLO0FRklmD2Upx0HCCQ==} engines: {node: '>=16.13'} @@ -27033,6 +27096,29 @@ packages: - utf-8-validate dev: true + /miniflare@3.20240512.0: + resolution: {integrity: sha512-X0PlKR0AROKpxFoJNmRtCMIuJxj+ngEcyTOlEokj2rAQ0TBwUhB4/1uiPvdI6ofW5NugPOD1uomAv+gLjwsLDQ==} + engines: {node: '>=16.13'} + hasBin: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + acorn: 8.10.0 + acorn-walk: 8.3.2 + capnp-ts: 0.7.0 + exit-hook: 2.2.1 + glob-to-regexp: 0.4.1 + stoppable: 1.1.0 + undici: 5.28.4 + workerd: 1.20240512.0 + ws: 8.16.0 + youch: 3.3.3 + zod: 3.22.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + /minimal-polyfills@2.2.2: resolution: {integrity: sha512-eEOUq/LH/DbLWihrxUP050Wi7H/N/I2dQT98Ep6SqOpmIbk4sXOI4wqalve66QoZa+6oljbZWU6I6T4dehQGmw==} dev: false @@ -31265,6 +31351,15 @@ packages: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + /resolve@2.0.0-next.4: resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} hasBin: true @@ -34034,6 +34129,7 @@ packages: dependencies: tslib: 1.14.1 typescript: 4.9.5 + dev: true /tsutils@3.21.0(typescript@5.0.4): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} @@ -34053,7 +34149,6 @@ packages: dependencies: tslib: 1.14.1 typescript: 5.1.6 - dev: false /tsutils@3.21.0(typescript@5.2.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} @@ -34477,6 +34572,13 @@ packages: dependencies: '@fastify/busboy': 2.0.0 + /undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.0.0 + dev: true + /unfetch@4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} dev: false @@ -35823,35 +35925,21 @@ packages: '@cloudflare/workerd-windows-64': 1.20231030.0 dev: true - /workerpool@6.2.1: - resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + /workerd@1.20240512.0: + resolution: {integrity: sha512-VUBmR1PscAPHEE0OF/G2K7/H1gnr9aDWWZzdkIgWfNKkv8dKFCT75H+GJtUHjfwqz3rYCzaNZmatSXOpLGpF8A==} + engines: {node: '>=16'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@cloudflare/workerd-darwin-64': 1.20240512.0 + '@cloudflare/workerd-darwin-arm64': 1.20240512.0 + '@cloudflare/workerd-linux-64': 1.20240512.0 + '@cloudflare/workerd-linux-arm64': 1.20240512.0 + '@cloudflare/workerd-windows-64': 1.20240512.0 dev: true - /wrangler@3.17.1: - resolution: {integrity: sha512-Pr9+/tjFkthzG63uoVm1NtVvgokT6p92fy1UsOgrntHyTu0pZMC1VJzG0NC8Vhs+z/+yTT8AqVV6AiJb3w8ZOQ==} - engines: {node: '>=16.17.0'} - hasBin: true - dependencies: - '@cloudflare/kv-asset-handler': 0.2.0 - '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) - '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) - blake3-wasm: 2.1.5 - chokidar: 3.5.3 - esbuild: 0.17.19 - miniflare: 3.20231030.1 - nanoid: 3.3.6 - path-to-regexp: 6.2.1 - resolve.exports: 2.0.2 - selfsigned: 2.4.1 - source-map: 0.6.1 - source-map-support: 0.5.21 - xxhash-wasm: 1.0.2 - optionalDependencies: - fsevents: 2.3.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate + /workerpool@6.2.1: + resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} dev: true /wrangler@3.18.0: @@ -35908,6 +35996,39 @@ packages: - utf-8-validate dev: true + /wrangler@3.57.1(@cloudflare/workers-types@4.20240512.0): + resolution: {integrity: sha512-M8YnWUwdrb8AFiRePtVnzlDn02OX4osWvdl8oVh6eyZqqkqXYg7lwlYBr14Qj92pMN4JvMBmDZoukkYHvwpJRg==} + engines: {node: '>=16.17.0'} + hasBin: true + peerDependencies: + '@cloudflare/workers-types': ^4.20240512.0 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + dependencies: + '@cloudflare/kv-asset-handler': 0.3.2 + '@cloudflare/workers-types': 4.20240512.0 + '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) + '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) + blake3-wasm: 2.1.5 + chokidar: 3.5.3 + esbuild: 0.17.19 + miniflare: 3.20240512.0 + nanoid: 3.3.7 + path-to-regexp: 6.2.1 + resolve: 1.22.8 + resolve.exports: 2.0.2 + selfsigned: 2.4.1 + source-map: 0.6.1 + xxhash-wasm: 1.0.2 + optionalDependencies: + fsevents: 2.3.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'}