From 037417e5031b17c9c370d773b9e1c3af7810d494 Mon Sep 17 00:00:00 2001 From: istarkov Date: Thu, 11 Jul 2024 13:03:33 +0000 Subject: [PATCH 1/2] build: Move rate-limit to cloudflare --- apps/builder/middleware.js | 467 ------------------------------------- apps/builder/package.json | 10 +- apps/builder/tsconfig.json | 8 +- pnpm-lock.yaml | 86 ------- 4 files changed, 2 insertions(+), 569 deletions(-) delete mode 100644 apps/builder/middleware.js diff --git a/apps/builder/middleware.js b/apps/builder/middleware.js deleted file mode 100644 index 85bb549f2cb9..000000000000 --- a/apps/builder/middleware.js +++ /dev/null @@ -1,467 +0,0 @@ -/** - * To test middleware locally: - * ```shell - * # At project root: - * pnpx vercel link - * pnpx vercel dev - * ``` - * - * OR - * - * ```shell - * # Link vercel project - * pnpm middleware:link - * # Initialize .env.preview - * pnpm middleware:env - * # Start middleware server - * pnpm middleware:dev - * ``` - * - * OR - * - * ```shell - * pnpx vercel link - * pnpx vercel env pull --environment=preview ./.env.preview - * pnpm tsx watch --env-file=.env.preview ./middleware.js - * ``` - */ -import { Ratelimit } from "@upstash/ratelimit"; -import { ipAddress, next as passthroughRaw } from "@vercel/edge"; -import { createClient } from "@vercel/kv"; -import { Hono } from "hono"; -import { HTTPException } from "hono/http-exception"; -import { env as envHono, getRuntimeKey } from "hono/adapter"; -import { handle } from "hono/vercel"; -import memoize from "memoize-one"; -import { createCookieSessionStorage } from "@remix-run/cloudflare"; - -/** - * ---------------------------------------------------------------- - * ---------------------======<<>>======-------------------- - * ---------------------------------------------------------------- - */ - -/** - * @typedef {object} Environment - * @property {string} KV_RATE_LIMIT_REST_API_TOKEN - * @property {string} KV_RATE_LIMIT_REST_API_URL - * @property {string} TRPC_SERVER_API_TOKEN - * @property {string} AUTH_SECRET - * - * @typedef {object} Variables - * @property {boolean} skipRateLimit - * - * @typedef {object} ContextEnv - * @property {Variables} Variables - */ - -/** - * ------------------------------------------------------------------ - * ---------------------======<<>>======------------------ - * ------------------------------------------------------------------ - */ - -/** - * @param {import('hono').Context} req - * @returns {Promise} - */ -let passthrough = async (req) => passthroughRaw(); - -/** @type {typeof envHono>} */ -const env = (ctx) => envHono(ctx); - -const getRateLimitMemoized = memoize( - /** - * @param {string} kvApiToken - * @param {string} kvUrl - */ - (kvApiToken, kvUrl) => { - const rateLimiterCache = new Map(); - - const kv = createClient({ - token: kvApiToken, - url: kvUrl, - }); - - const authorized = new Ratelimit({ - redis: kv, - limiter: Ratelimit.slidingWindow(20, "5 s"), - ephemeralCache: rateLimiterCache, - prefix: "authorized", - }); - - const unAuthorized = new Ratelimit({ - redis: kv, - limiter: Ratelimit.slidingWindow(10, "5 s"), - ephemeralCache: rateLimiterCache, - prefix: "unauthorized", - }); - - // No ephemeralCache for the AI endpoint - const ai = new Ratelimit({ - redis: kv, - limiter: Ratelimit.slidingWindow(20, "1 m"), - prefix: "ai", - // Usually during AI request we need few requests available, small timeout here could break things - timeout: 60000, - }); - - // For performance testing purposes - const perfTest = new Ratelimit({ - redis: kv, - limiter: Ratelimit.slidingWindow(12000, "600 s"), - prefix: "test", - }); - - const perfTestEphemeral = new Ratelimit({ - redis: kv, - limiter: Ratelimit.slidingWindow(12000, "600 s"), - ephemeralCache: rateLimiterCache, - prefix: "ephemeral", - }); - - return { - authorized, - unAuthorized, - ai, - perfTest, - perfTestEphemeral, - }; - } -); - -/** @param {import('hono').Context} ctx */ -const getRateLimits = (ctx) => { - const { KV_RATE_LIMIT_REST_API_TOKEN, KV_RATE_LIMIT_REST_API_URL } = env(ctx); - if (KV_RATE_LIMIT_REST_API_TOKEN === undefined) { - throw new HTTPException(500, { - message: "KV_RATE_LIMIT_REST_API_TOKEN env variable is undefined", - }); - } - - if (KV_RATE_LIMIT_REST_API_URL === undefined) { - throw new HTTPException(500, { - message: "KV_RATE_LIMIT_REST_API_URL env variable is undefined", - }); - } - - return getRateLimitMemoized( - KV_RATE_LIMIT_REST_API_TOKEN, - KV_RATE_LIMIT_REST_API_URL - ); -}; - -/** - * @todo: must be shared with 'apps/builder/app/services/cookie.server.ts' after ESM switch - */ -const getSessionStorageMemozied = memoize( - /** - * @param {string} authSecret - */ - (authSecret) => - createCookieSessionStorage({ - cookie: { - maxAge: 60 * 60 * 24 * 30, - name: "_session", - sameSite: "lax", - path: "/", - httpOnly: true, - secrets: authSecret ? [authSecret] : undefined, - secure: process.env.NODE_ENV === "production", - }, - }) -); - -/** @param {import('hono').Context} ctx */ -const getSessionStorage = (ctx) => { - const { AUTH_SECRET } = env(ctx); - - if (AUTH_SECRET === undefined) { - throw new HTTPException(500, { - message: "AUTH_SECRET env variable is undefined", - }); - } - - return getSessionStorageMemozied(AUTH_SECRET); -}; - -/** - * @param {import('hono').Context} ctx - */ -const getUserId = async (ctx) => { - const sessionStorage = getSessionStorage(ctx); - const { data } = await sessionStorage.getSession(ctx.req.header("Cookie")); - return data.user?.id; -}; - -/** - * @param {import('hono').Context} ctx - * @param {keyof ReturnType} ratelimitName - * @param {string} key - */ -const checkRateLimit = async (ctx, ratelimitName, key) => { - const rateLimits = getRateLimits(ctx); - const ratelimit = rateLimits[ratelimitName]; - - const { success, pending, limit, reset, remaining } = - await ratelimit.limit(key); - - if (getRuntimeKey() !== "node") { - try { - ctx.executionCtx.waitUntil(pending); - } catch { - /**/ - } - } - - if (success === false) { - // eslint-disable-next-line no-console - console.warn( - `ratelimit triggered: [${ratelimitName}] limit=${limit}, reset=${reset}, remaining=${remaining} key=${key}` - ); - - throw new HTTPException(429, { - res: ctx.json( - { - error: { - message: `ratelimit triggered: [${ratelimitName}] limit=${limit}, reset=${reset}, remaining=${remaining}, key=${key}`, - code: 429, - meta: { - limit, - reset, - remaining, - ratelimitName, - }, - }, - }, - 429 - ), - }); - } -}; - -/** - * ------------------------------------------------------------ - * ---------------------======<<>>======------------------ - * ------------------------------------------------------------ - */ - -/** @type {Hono} */ -const app = new Hono(); - -// Debug route, to show current values, MUST BE ABOVE middlewares -app.get("/rate-limit/debug", async (ctx) => { - const rateLimits = getRateLimits(ctx); - - const aiKey = `${ - (await getUserId(ctx)) ?? ipAddress(ctx.req) ?? "127.0.0.1" - }`; - - const userId = await getUserId(ctx); - - const ip = ipAddress(ctx.req) ?? "127.0.0.1"; - - return ctx.json({ - keys: { - aiKey, - userId, - ip, - }, - unAuthorized: await rateLimits.unAuthorized.limit(ip), - authorized: await rateLimits.authorized.limit(userId), - ai: await rateLimits.ai.limit(aiKey), - }); -}); - -// Debug route, to test the rate-limiting performance, MUST BE ABOVE middlewares -app.get("/rate-limit/test", async (ctx) => { - const rateLimits = getRateLimits(ctx); - - const aiKey = `${ - (await getUserId(ctx)) ?? ipAddress(ctx.req) ?? "127.0.0.1" - }`; - - return ctx.json({ - perfTest: await rateLimits.perfTest.limit(aiKey), - }); -}); - -// Debug route, to test the rate-limiting performance with ephemeral cache, MUST BE ABOVE middlewares -app.get("/rate-limit/ephemeral-test", async (ctx) => { - const rateLimits = getRateLimits(ctx); - - const aiKey = `${ - (await getUserId(ctx)) ?? ipAddress(ctx.req) ?? "127.0.0.1" - }`; - - return ctx.json({ - perfTest: await rateLimits.perfTestEphemeral.limit(aiKey), - }); -}); - -/** - * Check whether the request is for a static file; if so, bypass the rate-limiting mechanism. - */ -app.use("*", async (ctx, next) => { - const skipRateLimit = ctx.get("skipRateLimit"); - if (skipRateLimit) { - return next(); - } - - const url = new URL(ctx.req.url); - - ctx.set( - "skipRateLimit", - url.pathname.startsWith("/asset/") || - url.pathname.startsWith("/assets/") || - url.pathname.endsWith(".ico") - ); - return next(); -}); - -/** - * Check whether the request is a service call; if so, bypass the rate-limiting mechanism. - */ -app.use("*", async (ctx, next) => { - const skipRateLimit = ctx.get("skipRateLimit"); - if (skipRateLimit) { - return next(); - } - - const { TRPC_SERVER_API_TOKEN } = env(ctx); - - if (TRPC_SERVER_API_TOKEN === undefined) { - throw new HTTPException(500, { - message: "TRPC_SERVER_API_TOKEN env variable is undefined", - }); - } - - const isServiceCall = - TRPC_SERVER_API_TOKEN !== undefined && - ctx.req.header("Authorization") === TRPC_SERVER_API_TOKEN; - - ctx.set("skipRateLimit", isServiceCall); - - return next(); -}); - -/** - * Rate limiting AI endpoint, max priority - */ -app.use("/rest/ai/*", async (ctx, next) => { - const skipRateLimit = ctx.get("skipRateLimit"); - if (skipRateLimit) { - return next(); - } - - const aiKey = `${ - (await getUserId(ctx)) ?? ipAddress(ctx.req) ?? "127.0.0.1" - }`; - - await checkRateLimit(ctx, "ai", aiKey); - ctx.set("skipRateLimit", true); - - return next(); -}); - -/** - * Rate limiting authorized/unauthorized users - */ -app.use("*", async (ctx, next) => { - const skipRateLimit = ctx.get("skipRateLimit"); - if (skipRateLimit) { - return next(); - } - - const userId = await getUserId(ctx); - - if (userId === undefined) { - await checkRateLimit( - ctx, - "unAuthorized", - ipAddress(ctx.req) ?? "127.0.0.1" - ); - ctx.set("skipRateLimit", true); - return next(); - } - - await checkRateLimit(ctx, "authorized", userId); - - ctx.set("skipRateLimit", true); - - return next(); -}); - -app.notFound(async (ctx) => { - return passthrough(ctx); -}); - -app.onError(async (err, ctx) => { - if (err instanceof HTTPException) { - return err.getResponse(); - } - - console.error(err.stack ?? err); - - return ctx.json({ cause: err.cause, message: err.message }); -}); - -export default handle(app); - -/** - * -------------------------------------------------------------------- - * ---------------------======<<>>======------------------ - * -------------------------------------------------------------------- - */ - -if (process.env.NODE_ENV !== "production") { - if (getRuntimeKey() === "node") { - // To avoid vercel dev errors on build - const modulePath = "" + "@hono/node-server"; - /** @type {Promise} */ - const importedModule = import(modulePath); - - importedModule.then(({ serve }) => { - serve({ ...app, port: 3002 }, (info) => { - console.info(`Listening on http://localhost:${info.port}`); - }); - }); - - passthrough = async (ctx) => { - try { - const devUrl = new URL(ctx.req.url); - devUrl.port = "3000"; - - const raw = ctx.req.raw; - - const req = new Request(devUrl, { - headers: raw.headers, - method: raw.method, - body: raw.body, - redirect: "manual", - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - duplex: "half", - }); - - const res = await fetch(req); - - const responseHeaders = new Headers(res.headers); - responseHeaders.delete("content-encoding"); - - return new Response(res.body, { - status: res.status, - statusText: res.statusText, - headers: responseHeaders, - }); - } catch (error) { - throw new HTTPException(500, { - message: - error instanceof Error - ? `Middlewared dev fetch error ${error.message}` - : "Middlewared dev fetch error", - }); - } - }; - } -} diff --git a/apps/builder/package.json b/apps/builder/package.json index b84c5e639049..9ec563b11337 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -13,10 +13,7 @@ "dev": "remix vite:dev", "typecheck": "tsc --noEmit --emitDeclarationOnly false", "test": "NODE_OPTIONS=--experimental-vm-modules jest", - "ci:migrate": "migrations migrate", - "middleware:link": "pnpx vercel link", - "middleware:env": "pnpx vercel env pull --environment=preview ./.env.preview", - "middleware:dev": "tsx watch --env-file=.env.preview ./middleware.js" + "ci:migrate": "migrations migrate" }, "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.1.11", @@ -50,9 +47,6 @@ "@remix-run/server-runtime": "^2.10.0", "@trpc/client": "^10.38.1", "@trpc/server": "^10.38.1", - "@upstash/ratelimit": "^0.4.4", - "@vercel/edge": "^1.1.0", - "@vercel/kv": "^0.2.3", "@vercel/remix": "2.9.2", "@webstudio-is/ai": "workspace:*", "@webstudio-is/asset-uploader": "workspace:*", @@ -87,7 +81,6 @@ "detect-font": "^0.1.5", "downshift": "^6.1.7", "fast-deep-equal": "^3.1.3", - "hono": "^3.7.3", "immer": "^10.0.3", "immerhin": "^0.9.0", "lexical": "^0.16.0", @@ -125,7 +118,6 @@ "zod": "^3.22.4" }, "devDependencies": { - "@hono/node-server": "^1.2.0", "@jest/globals": "^29.7.0", "@remix-run/dev": "^2.10.0", "@testing-library/react-hooks": "^8.0.1", diff --git a/apps/builder/tsconfig.json b/apps/builder/tsconfig.json index bea7d5128c1b..8537753492d7 100644 --- a/apps/builder/tsconfig.json +++ b/apps/builder/tsconfig.json @@ -1,12 +1,6 @@ { "extends": "@webstudio-is/tsconfig/base.json", - "include": [ - "app", - "**/*.ts", - "**/*.tsx", - "../../@types/**/*.d.ts", - "./middleware.js" - ], + "include": ["app", "**/*.ts", "**/*.tsx", "../../@types/**/*.d.ts"], "compilerOptions": { "types": ["@remix-run/node", "vite/client"], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd23cb96a537..cdafdc585ecb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,15 +196,6 @@ importers: '@trpc/server': specifier: ^10.38.1 version: 10.38.1 - '@upstash/ratelimit': - specifier: ^0.4.4 - version: 0.4.4 - '@vercel/edge': - specifier: ^1.1.0 - version: 1.1.0 - '@vercel/kv': - specifier: ^0.2.3 - version: 0.2.3 '@vercel/remix': specifier: 2.9.2 version: 2.9.2(@remix-run/dev@2.10.0(@remix-run/react@2.10.0(react-dom@18.3.0-canary-14898b6a9-20240318(react@18.3.0-canary-14898b6a9-20240318))(react@18.3.0-canary-14898b6a9-20240318)(typescript@5.5.2))(@remix-run/serve@2.10.0(typescript@5.5.2))(@types/node@20.12.7)(typescript@5.5.2)(vite@5.3.2(@types/node@20.12.7))(wrangler@3.63.2(@cloudflare/workers-types@4.20240701.0)))(@remix-run/node@2.10.0(typescript@5.5.2))(@remix-run/server-runtime@2.10.0(typescript@5.5.2))(react-dom@18.3.0-canary-14898b6a9-20240318(react@18.3.0-canary-14898b6a9-20240318))(react@18.3.0-canary-14898b6a9-20240318) @@ -307,9 +298,6 @@ importers: fast-deep-equal: specifier: ^3.1.3 version: 3.1.3 - hono: - specifier: ^3.7.3 - version: 3.7.3 immer: specifier: ^10.0.3 version: 10.0.3 @@ -416,9 +404,6 @@ importers: specifier: ^3.22.4 version: 3.22.4 devDependencies: - '@hono/node-server': - specifier: ^1.2.0 - version: 1.2.0 '@jest/globals': specifier: ^29.7.0 version: 29.7.0 @@ -3666,10 +3651,6 @@ packages: engines: {node: '>=6'} hasBin: true - '@hono/node-server@1.2.0': - resolution: {integrity: sha512-aHT8lDMLpd7ioXJ1/057+h+oE/k7rCOWmjklYDsE0jE4CoNB9XzG4f8dRHvw4s5HJFocaYDiGgYM/V0kYbQ0ww==} - engines: {node: '>=18.0.0'} - '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -5547,19 +5528,6 @@ packages: resolution: {integrity: sha512-E0FbNzIk8TkVUF+kZGscDEmfYHps8/9qjvwJK6BjbbnxTaBPoSY9DQjsGWcCiD9pUKJt2tquNwADPiYzzkiKtA==} engines: {node: '>=14'} - '@upstash/core-analytics@0.0.6': - resolution: {integrity: sha512-cpPSR0XJAJs4Ddz9nq3tINlPS5aLfWVCqhhtHnXt4p7qr5+/Znlt1Es736poB/9rnl1hAHrOsOvVj46NEXcVqA==} - engines: {node: '>=16.0.0'} - - '@upstash/ratelimit@0.4.4': - resolution: {integrity: sha512-y3q6cNDdcRQ2MRPRf5UNWBN36IwnZ4kAEkGoH3i6OqdWwz4qlBxNsw4/Rpqn9h93+Nx1cqg5IOq7O2e2zMJY1w==} - - '@upstash/redis@1.22.0': - resolution: {integrity: sha512-sXoJDoEqqik0HbrNE7yRWckOySEFsoBxfRdCgOqkc0w6py19ZZG50SpGkDDEUXSnBqP8VgGYXhWAiBpqxrt5oA==} - - '@upstash/redis@1.22.1': - resolution: {integrity: sha512-7ec2eCMkVxZzuHNb+hPKonX4b/Pu0BdDeSBsEy+jKIqiweXzCs5Dpu9642vJgf57YnEsfwgXnQMVEataarvyeQ==} - '@vanilla-extract/babel-plugin-debug-ids@1.0.6': resolution: {integrity: sha512-C188vUEYmw41yxg3QooTs8r1IdbDQQ2mH7L5RkORBnHx74QlmsNfqVmKwAVTgrlYt8JoRaWMtPfGm/Ql0BNQrA==} @@ -5572,13 +5540,6 @@ packages: '@vanilla-extract/private@1.0.5': resolution: {integrity: sha512-6YXeOEKYTA3UV+RC8DeAjFk+/okoNz/h88R+McnzA2zpaVqTR/Ep+vszkWYlGBcMNO7vEkqbq5nT/JMMvhi+tw==} - '@vercel/edge@1.1.0': - resolution: {integrity: sha512-84H2EavY5Kul9Ef1DnTH0XEG5vChqcXjyqoRLVPjjZjLWw47sMapzXXQH09pybcshR+8AKqULGvFqPTWuRh3Rw==} - - '@vercel/kv@0.2.3': - resolution: {integrity: sha512-Wq1+EsRBQmvLlcqCZeYVg1MAARWrnETgLe3Sy3UCqG+zg7LThpkt0YHZe1NN3Aj4IRmCKQamotWrLDdEx+ZB3w==} - engines: {node: '>=14.6'} - '@vercel/remix@2.9.2': resolution: {integrity: sha512-3aTvWCS5U4bAkokhEVndcm9FyFv0/pW49b4qvcXIUyMi+vMNH4KTgPUbfeBDDtG7MLKFiQAYPUVr6rzc5ZtWkg==} engines: {node: '>=18.0.0'} @@ -7098,10 +7059,6 @@ packages: hast-util-whitespace@2.0.1: resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} - hono@3.7.3: - resolution: {integrity: sha512-BQHdLPXb30hQ9k+04byeSi4QMHk20U1GUq0nT5kGUCGZtxeYhAS7mUJ1wgjn4SCvgiw1rcc6oBOAlwJQ7jQymA==} - engines: {node: '>=16.0.0'} - hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -7423,9 +7380,6 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - isomorphic-fetch@3.0.0: - resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} - isomorphic.js@0.2.5: resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} @@ -10016,9 +9970,6 @@ packages: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} - whatwg-fetch@3.6.19: - resolution: {integrity: sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==} - whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} @@ -11760,8 +11711,6 @@ snapshots: protobufjs: 7.3.2 yargs: 17.7.2 - '@hono/node-server@1.2.0': {} - '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -14497,30 +14446,6 @@ snapshots: '@unocss/core': 0.61.2 magic-string: 0.30.10 - '@upstash/core-analytics@0.0.6': - dependencies: - '@upstash/redis': 1.22.1 - transitivePeerDependencies: - - encoding - - '@upstash/ratelimit@0.4.4': - dependencies: - '@upstash/core-analytics': 0.0.6 - transitivePeerDependencies: - - encoding - - '@upstash/redis@1.22.0': - dependencies: - isomorphic-fetch: 3.0.0 - transitivePeerDependencies: - - encoding - - '@upstash/redis@1.22.1': - dependencies: - isomorphic-fetch: 3.0.0 - transitivePeerDependencies: - - encoding - '@vanilla-extract/babel-plugin-debug-ids@1.0.6': dependencies: '@babel/core': 7.24.5 @@ -16392,8 +16317,6 @@ snapshots: hast-util-whitespace@2.0.1: {} - hono@3.7.3: {} - hosted-git-info@2.8.9: {} hosted-git-info@6.1.1: @@ -16678,13 +16601,6 @@ snapshots: isobject@3.0.1: {} - isomorphic-fetch@3.0.0: - dependencies: - node-fetch: 2.6.9 - whatwg-fetch: 3.6.19 - transitivePeerDependencies: - - encoding - isomorphic.js@0.2.5: {} istanbul-lib-coverage@3.2.0: {} @@ -19926,8 +19842,6 @@ snapshots: dependencies: iconv-lite: 0.6.3 - whatwg-fetch@3.6.19: {} - whatwg-mimetype@3.0.0: {} whatwg-url@11.0.0: From 7819f9461b7f6cbd73217981b350e5c505c15e31 Mon Sep 17 00:00:00 2001 From: istarkov Date: Thu, 11 Jul 2024 19:44:51 +0000 Subject: [PATCH 2/2] memoize --- apps/builder/package.json | 1 - pnpm-lock.yaml | 8 -------- 2 files changed, 9 deletions(-) diff --git a/apps/builder/package.json b/apps/builder/package.json index 9ec563b11337..429c283ceaea 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -87,7 +87,6 @@ "match-sorter": "^6.3.1", "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm": "^3.0.0", - "memoize-one": "^6.0.0", "micromark-extension-gfm": "^3.0.0", "nanoevents": "^8.0.0", "nanoid": "^5.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdafdc585ecb..f86a454d5936 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -316,9 +316,6 @@ importers: mdast-util-gfm: specifier: ^3.0.0 version: 3.0.0 - memoize-one: - specifier: ^6.0.0 - version: 6.0.0 micromark-extension-gfm: specifier: ^3.0.0 version: 3.0.0 @@ -7870,9 +7867,6 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - memoize-one@6.0.0: - resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} - memoize@10.0.0: resolution: {integrity: sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==} engines: {node: '>=18'} @@ -17442,8 +17436,6 @@ snapshots: media-typer@0.3.0: {} - memoize-one@6.0.0: {} - memoize@10.0.0: dependencies: mimic-function: 5.0.1