From ba41093747ab5ef25a1c17b9d2b48b220b28fda7 Mon Sep 17 00:00:00 2001 From: Abdulkaiz Khatri <24286590+ful1e5@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:13:36 +0530 Subject: [PATCH] chore(redis): use '@vercel/kv' instead 'ioredis' --- .env.example | 38 +++++++++++++++++ package.json | 2 +- src/app/api/svg/[id]/route.ts | 5 +-- src/app/api/svg/fetch/route.ts | 3 +- src/app/api/svg/route.ts | 5 +-- src/services/kv.ts | 33 +++++++++++++++ src/services/redis.ts | 59 -------------------------- src/types/env.d.ts | 4 -- yarn.lock | 76 +++++++++------------------------- 9 files changed, 96 insertions(+), 129 deletions(-) create mode 100644 .env.example create mode 100644 src/services/kv.ts delete mode 100644 src/services/redis.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c2dbfbf --- /dev/null +++ b/.env.example @@ -0,0 +1,38 @@ +# +# Necessary +# +POSTGRES_PRISMA_URL=postgresql://:@localhost:5432/bibata +POSTGRES_URL_NON_POOLING=postgresql://:@localhost:5432/bibata + +# Run docker container first +# docker run \ +# -it -d -p 8080:80 --name bibata-dev-kv \ +# -e SRH_MODE=env \ +# -e SRH_TOKEN=supertoken \ +# -e SRH_CONNECTION_STRING="redis://localhost:6379" \ +# hiett/serverless-redis-http:latest +KV_URL=http://localhost:8080 +KV_REST_API_URL=http://localhost:8080/rest +KV_REST_API_TOKEN=supertoken + +GITHUB_ID= +GITHUB_SECRET= + +FIGMA_TOKEN= +FIGMA_FILE= + +# +# Secrets +# +# for secret generation run: openssl rand -base64 32 +NEXTAUTH_SECRET= +NEXT_PUBLIC_JWT_SECRET= +FLASK_SECRET= +SVG_FETCH_SECRET= + +# +# Dev Only +# +VERCEL_ENV=development +FLASK_ENV=development +NEXTAUTH_URL=http://localhost:3000/api/auth/ diff --git a/package.json b/package.json index 065a376..d72a2db 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "dependencies": { "@prisma/client": "^5.5.2", "@uiw/react-color-wheel": "^1.4.2", + "@vercel/kv": "^1.0.0", "concurrently": "^8.0.1", "figma-api": "^1.11.0", - "ioredis": "^5.3.2", "jsonwebtoken": "^8.5.1", "localstorage-slim": "^2.6.0", "next": "^14.0.0", diff --git a/src/app/api/svg/[id]/route.ts b/src/app/api/svg/[id]/route.ts index 4108803..bd70f38 100644 --- a/src/app/api/svg/[id]/route.ts +++ b/src/app/api/svg/[id]/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; -import { ImageRedis } from '@services/redis'; +import { ImageRedis } from '@services/kv'; import { FetchSVG } from '@utils/figma/fetch-svgs'; import { RESPONSES as res } from '@api/config'; @@ -21,7 +21,7 @@ export async function GET(request: NextRequest, { params }: Param) { if (id) { try { const redis = new ImageRedis(); - const raw = await redis.get(id); + const raw = (await redis.get(id)) as string; if (!raw) return res.image_not_found; @@ -36,7 +36,6 @@ export async function GET(request: NextRequest, { params }: Param) { data.push(`data:image/png;base64,${img!.toString('base64')}`); } - await redis.client.quit(); if (data) { return NextResponse.json({ data }); } else { diff --git a/src/app/api/svg/fetch/route.ts b/src/app/api/svg/fetch/route.ts index be7cd27..e3ebf1a 100644 --- a/src/app/api/svg/fetch/route.ts +++ b/src/app/api/svg/fetch/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; -import { ImageRedis } from '@services/redis'; +import { ImageRedis } from '@services/kv'; import { FetchSVG } from '@utils/figma/fetch-svgs'; @@ -57,7 +57,6 @@ const update = async () => { } } - await redis.client.quit(); return; } catch (e) { if (e instanceof Error) { diff --git a/src/app/api/svg/route.ts b/src/app/api/svg/route.ts index 29aba6e..76567c8 100644 --- a/src/app/api/svg/route.ts +++ b/src/app/api/svg/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; -import { ImageRedis } from '@services/redis'; +import { ImageRedis } from '@services/kv'; import { TYPES } from '@root/configs'; import { RESPONSES as res } from '@api/config'; @@ -17,14 +17,13 @@ export async function GET(request: NextRequest) { const redis = new ImageRedis(); const data: SVG[] = await redis .get(type) - .then((s) => JSON.parse(s || '[]')); + .then((s) => JSON.parse((s as string) || '[]')); const error = data.length === 0 ? "Oops! It looks like there's a little hiccup fetching the SVG nodes right now." : null; - await redis.client.quit(); return NextResponse.json( { error, data }, { status: error ? 404 : 200 } diff --git a/src/services/kv.ts b/src/services/kv.ts new file mode 100644 index 0000000..7f46fa1 --- /dev/null +++ b/src/services/kv.ts @@ -0,0 +1,33 @@ +import { kv } from '@vercel/kv'; + +import { SVG } from 'bibata/app'; + +export class ImageRedis { + constructor() {} + + public async del(key: string) { + return await kv.del(key); + } + + public async get(key: string) { + return await kv.get(key); + } + + public async saveSVGs(key: string, value: SVG[]) { + const res = await kv.set(key, JSON.stringify(value)); + res && console.info(`Updated Type '${key}'`); + } + + public async rmOldUrls() { + const keys = await kv.keys('i-*'); + if (keys && keys.length > 0) { + const num = await kv.del(...keys); + console.log(`Deleted ${num} URLs.`); + } + } + + public async saveUrls(key: string, name: string, urls: (string | null)[]) { + const res = await kv.set(key, JSON.stringify(urls)); + res && console.info(`Updated '${name}':`); + } +} diff --git a/src/services/redis.ts b/src/services/redis.ts deleted file mode 100644 index 8c6b93c..0000000 --- a/src/services/redis.ts +++ /dev/null @@ -1,59 +0,0 @@ -import Redis, { RedisKey } from 'ioredis'; - -import { SVG } from 'bibata/app'; - -export class ImageRedis { - client: Redis; - - constructor() { - this.client = this.__connect(); - } - - private __connect() { - const client: Redis = new Redis({ - host: process.env.REDIS_HOST, - port: process.env.REDIS_PORT, - password: process.env.REDIS_PASSWORD, - lazyConnect: true - }); - client.on('ready', () => { - console.info('Redis cluster Ready'); - }); - client.on('error', (error) => { - console.error(`Redis cluster Connection Error: ${error}`); - }); - client.on('end', () => { - console.info('Redis cluster Connection ended'); - }); - - return client; - } - - public async del(key: RedisKey) { - return await this.client.del(key); - } - - public async get(key: RedisKey) { - return await this.client.get(key); - } - - public async saveSVGs(key: RedisKey, value: SVG[]) { - await this.client.set(key, JSON.stringify(value), (s) => { - s && console.info(`Updated Type '${key}': ${s} `); - }); - } - - public async rmOldUrls() { - const keys = await this.client.keys('i-*'); - if (keys && keys.length > 0) { - const num = await this.client.del(...keys); - console.log(`Deleted ${num} URLs.`); - } - } - - public async saveUrls(key: RedisKey, name: string, urls: (string | null)[]) { - return await this.client.set(key, JSON.stringify(urls), (s) => { - s && console.info(`Updated '${name}': ${s} `); - }); - } -} diff --git a/src/types/env.d.ts b/src/types/env.d.ts index 3133922..e4297d7 100644 --- a/src/types/env.d.ts +++ b/src/types/env.d.ts @@ -7,10 +7,6 @@ namespace NodeJS { readonly FLASK_SECRET: string; readonly SVG_FETCH_SECRET: string; - readonly REDIS_HOST?: string; - readonly REDIS_PORT?: number; - readonly REDIS_PASSWORD?: string; - readonly GITHUB_ID: string; readonly GITHUB_SECRET: string; diff --git a/yarn.lock b/yarn.lock index 4a4d700..c2dd66f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -70,11 +70,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== -"@ioredis/commands@^1.1.1": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" - integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== - "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -337,6 +332,20 @@ resolved "https://registry.yarnpkg.com/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-1.4.3.tgz#9e32bf06bf23242fa5c03286f3ac0f06cab45bd1" integrity sha512-PTCWPM9tx7X6bPe2PBawqpEbYKHxuuUwq+O1tfCZBcNCjEc0FI0kp3VTyIzrO5onCzG4sC2vUIWHxHE7and+2Q== +"@upstash/redis@1.24.3": + version "1.24.3" + resolved "https://registry.yarnpkg.com/@upstash/redis/-/redis-1.24.3.tgz#0247250f7e26b6923e6ce4f348ce08f7bbdc6222" + integrity sha512-gw6d4IA1biB4eye5ESaXc0zOlVQI94aptsBvVcTghYWu1kRmOrJFoMFEDCa8p5uzluyYAOFCuY2GWLR6O4ZoIw== + dependencies: + crypto-js "^4.2.0" + +"@vercel/kv@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@vercel/kv/-/kv-1.0.0.tgz#9ae4716dd01f097aaab25259217c13a9d18ef922" + integrity sha512-StouXunmEqUfKE+1joSYfELWEEnI1MhTnzUdarHtv6H18RAm3cf5u5g9ElvA1DJNHcrMT6g5yVAhZcYRbk6lvg== + dependencies: + "@upstash/redis" "1.24.3" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -666,11 +675,6 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -cluster-key-slot@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" - integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -738,6 +742,11 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -809,11 +818,6 @@ define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, de has-property-descriptors "^1.0.0" object-keys "^1.1.1" -denque@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" - integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== - dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -1568,21 +1572,6 @@ internal-slot@^1.0.5: hasown "^2.0.0" side-channel "^1.0.4" -ioredis@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7" - integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA== - dependencies: - "@ioredis/commands" "^1.1.1" - cluster-key-slot "^1.1.0" - debug "^4.3.4" - denque "^2.1.0" - lodash.defaults "^4.2.0" - lodash.isarguments "^3.1.0" - redis-errors "^1.2.0" - redis-parser "^3.0.0" - standard-as-callback "^2.1.0" - is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" @@ -1926,21 +1915,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.defaults@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== - lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== -lodash.isarguments@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== - lodash.isboolean@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" @@ -2499,18 +2478,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -redis-errors@^1.0.0, redis-errors@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" - integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== - -redis-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" - integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== - dependencies: - redis-errors "^1.0.0" - reflect.getprototypeof@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" @@ -2739,11 +2706,6 @@ spawn-command@0.0.2: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== -standard-as-callback@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" - integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== - streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"