From 2e8950c71298147a7acc3d2131499cb466233054 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:16:49 +0530 Subject: [PATCH 01/12] feat: prisma for db --- apps/api/.env.example | 1 + .../migrations/20231119144606_/migration.sql | 100 ++++++++++++++++++ apps/api/db/migrations/migration_lock.toml | 3 + apps/api/db/schema.prisma | 84 +++++++++++++++ apps/api/package.json | 6 ++ apps/api/utils/prisma.ts | 5 + pnpm-lock.yaml | 36 +++++++ 7 files changed, 235 insertions(+) create mode 100644 apps/api/db/migrations/20231119144606_/migration.sql create mode 100644 apps/api/db/migrations/migration_lock.toml create mode 100644 apps/api/db/schema.prisma create mode 100644 apps/api/utils/prisma.ts diff --git a/apps/api/.env.example b/apps/api/.env.example index 3b4d1591c254..1b7fc3c4ef72 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -1,4 +1,5 @@ SUPABASE_KEY="" +DATABASE_URL="" CLICKHOUSE_PASSWORD="" SECRET="secret" LIVEPEER_API_KEY="" diff --git a/apps/api/db/migrations/20231119144606_/migration.sql b/apps/api/db/migrations/20231119144606_/migration.sql new file mode 100644 index 000000000000..7ef27279c65a --- /dev/null +++ b/apps/api/db/migrations/20231119144606_/migration.sql @@ -0,0 +1,100 @@ +-- CreateEnum +CREATE TYPE "StaffPickType" AS ENUM ('PROFILE', 'GROUP'); + +-- CreateTable +CREATE TABLE "Verified" ( + "id" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Verified_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "StaffPick" ( + "id" TEXT NOT NULL, + "type" "StaffPickType" NOT NULL, + "score" INTEGER NOT NULL DEFAULT 0, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "StaffPick_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Preference" ( + "id" TEXT NOT NULL, + "isPride" BOOLEAN NOT NULL DEFAULT false, + "highSignalNotificationFilter" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Preference_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MembershipNft" ( + "id" TEXT NOT NULL, + "dismissedOrMinted" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "MembershipNft_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Group" ( + "id" TEXT NOT NULL, + "slug" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "avatar" TEXT NOT NULL, + "tags" TEXT[], + "lens" TEXT, + "x" TEXT, + "discord" TEXT, + "instagram" TEXT, + "featured" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Group_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Pro" ( + "id" TEXT NOT NULL, + "profileId" TEXT NOT NULL, + "hash" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "expiresAt" TIMESTAMP(3), + + CONSTRAINT "Pro_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Feature" ( + "id" TEXT NOT NULL, + "key" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT NOT NULL, + "priority" INTEGER NOT NULL DEFAULT 0, + "enabled" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Feature_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ProfileFeature" ( + "profileId" TEXT NOT NULL, + "featureId" TEXT NOT NULL, + "enabled" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "ProfileFeature_pkey" PRIMARY KEY ("profileId","featureId") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Group_slug_key" ON "Group"("slug"); + +-- CreateIndex +CREATE UNIQUE INDEX "Feature_key_key" ON "Feature"("key"); + +-- AddForeignKey +ALTER TABLE "ProfileFeature" ADD CONSTRAINT "ProfileFeature_featureId_fkey" FOREIGN KEY ("featureId") REFERENCES "Feature"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/api/db/migrations/migration_lock.toml b/apps/api/db/migrations/migration_lock.toml new file mode 100644 index 000000000000..fbffa92c2bb7 --- /dev/null +++ b/apps/api/db/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (i.e. Git) +provider = "postgresql" \ No newline at end of file diff --git a/apps/api/db/schema.prisma b/apps/api/db/schema.prisma new file mode 100644 index 000000000000..cf9b608fde74 --- /dev/null +++ b/apps/api/db/schema.prisma @@ -0,0 +1,84 @@ +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +model Verified { + id String @id @default(uuid()) + createdAt DateTime @default(now()) +} + +model StaffPick { + id String @id @default(uuid()) + type StaffPickType + score Int @default(0) + createdAt DateTime @default(now()) +} + +model Preference { + id String @id @default(uuid()) + isPride Boolean @default(false) + highSignalNotificationFilter Boolean @default(false) + createdAt DateTime @default(now()) +} + +model MembershipNft { + id String @id @default(uuid()) + dismissedOrMinted Boolean @default(false) + createdAt DateTime @default(now()) +} + +model Group { + id String @id @default(uuid()) + slug String @unique + name String + description String + avatar String + tags String[] + lens String? + x String? + discord String? + instagram String? + featured Boolean @default(false) + createdAt DateTime @default(now()) +} + +model Pro { + id String @id @default(uuid()) + profileId String + hash String + createdAt DateTime @default(now()) + expiresAt DateTime? +} + +model Feature { + id String @id @default(uuid()) + key String @unique + name String + description String + priority Int @default(0) + enabled Boolean @default(true) + createdAt DateTime @default(now()) + + // Relations + profiles ProfileFeature[] +} + +model ProfileFeature { + profileId String + featureId String + feature Feature @relation(fields: [featureId], references: [id], onDelete: Cascade) + enabled Boolean @default(true) + createdAt DateTime @default(now()) + + @@id([profileId, featureId]) +} + +enum StaffPickType { + PROFILE + GROUP +} diff --git a/apps/api/package.json b/apps/api/package.json index 3a7d7867d3bc..d97b7f00179d 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -10,6 +10,10 @@ "lint:fix": "eslint . --fix --ext .js,.ts,.tsx", "prettier": "prettier --check \"**/*.{js,ts,tsx,md}\" --cache", "prettier:fix": "prettier --write \"**/*.{js,ts,tsx,md}\" --cache", + "prisma:generate": "prisma generate --schema ./db/schema.prisma", + "prisma:migrate": "prisma migrate dev --schema ./db/schema.prisma", + "prisma:studio": "prisma studio --schema ./db/schema.prisma", + "prisma:format": "prisma format --schema ./db/schema.prisma", "start": "next start --port 4785", "test:dev": "vitest run", "typecheck": "tsc --pretty" @@ -20,6 +24,7 @@ "@hey/data": "workspace:*", "@hey/lib": "workspace:*", "@irys/sdk": "^0.0.4", + "@prisma/client": "^5.6.0", "@supabase/supabase-js": "^2.38.4", "axios": "^1.6.2", "fast-xml-parser": "^4.3.2", @@ -40,6 +45,7 @@ "@types/react": "^18.2.37", "@types/request-ip": "^0.0.41", "@types/ua-parser-js": "^0.7.39", + "prisma": "^5.6.0", "typescript": "^5.2.2", "vitest": "^0.34.5" } diff --git a/apps/api/utils/prisma.ts b/apps/api/utils/prisma.ts new file mode 100644 index 000000000000..f9ecc9d6804c --- /dev/null +++ b/apps/api/utils/prisma.ts @@ -0,0 +1,5 @@ +import { PrismaClient } from '@prisma/client/edge'; + +const prisma = new PrismaClient(); + +export default prisma; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d98f0d2d158f..be1de82dae90 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: '@irys/sdk': specifier: ^0.0.4 version: 0.0.4(arweave@1.14.4) + '@prisma/client': + specifier: ^5.6.0 + version: 5.6.0(prisma@5.6.0) '@supabase/supabase-js': specifier: ^2.38.4 version: 2.38.4 @@ -96,6 +99,9 @@ importers: '@types/ua-parser-js': specifier: ^0.7.39 version: 0.7.39 + prisma: + specifier: ^5.6.0 + version: 5.6.0 typescript: specifier: ^5.2.2 version: 5.2.2 @@ -4144,6 +4150,28 @@ packages: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: false + /@prisma/client@5.6.0(prisma@5.6.0): + resolution: {integrity: sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug==} + engines: {node: '>=16.13'} + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + '@prisma/engines-version': 5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee + prisma: 5.6.0 + dev: false + + /@prisma/engines-version@5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee: + resolution: {integrity: sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw==} + dev: false + + /@prisma/engines@5.6.0: + resolution: {integrity: sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw==} + requiresBuild: true + /@radix-ui/number@1.0.1: resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==} dependencies: @@ -11542,6 +11570,14 @@ packages: react-is: 18.2.0 dev: true + /prisma@5.6.0: + resolution: {integrity: sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A==} + engines: {node: '>=16.13'} + hasBin: true + requiresBuild: true + dependencies: + '@prisma/engines': 5.6.0 + /prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} From 484e736f222edec8eeda86b48bedae011f918d64 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:28:41 +0530 Subject: [PATCH 02/12] chore: migrate to prisma --- apps/api/package.json | 2 +- apps/api/pages/api/feature/getFeatureFlags.ts | 27 +++++++++---------- apps/api/pages/api/feature/getVerified.ts | 11 +++----- apps/api/utils/prisma.ts | 2 +- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/apps/api/package.json b/apps/api/package.json index d97b7f00179d..3e9593df7538 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -10,10 +10,10 @@ "lint:fix": "eslint . --fix --ext .js,.ts,.tsx", "prettier": "prettier --check \"**/*.{js,ts,tsx,md}\" --cache", "prettier:fix": "prettier --write \"**/*.{js,ts,tsx,md}\" --cache", + "prisma:format": "prisma format --schema ./db/schema.prisma", "prisma:generate": "prisma generate --schema ./db/schema.prisma", "prisma:migrate": "prisma migrate dev --schema ./db/schema.prisma", "prisma:studio": "prisma studio --schema ./db/schema.prisma", - "prisma:format": "prisma format --schema ./db/schema.prisma", "start": "next start --port 4785", "test:dev": "vitest run", "typecheck": "tsc --pretty" diff --git a/apps/api/pages/api/feature/getFeatureFlags.ts b/apps/api/pages/api/feature/getFeatureFlags.ts index 3b0e10af482d..40f30e5d5f32 100644 --- a/apps/api/pages/api/feature/getFeatureFlags.ts +++ b/apps/api/pages/api/feature/getFeatureFlags.ts @@ -2,7 +2,7 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (req: NextApiRequest, res: NextApiResponse) => { @@ -23,19 +23,18 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { .json({ success: true, cached: true, features: JSON.parse(cache) }); } - const client = createSupabaseClient(); - const { data, error } = await client - .from('profile-features') - .select('profile_id, enabled, features!inner(key, enabled)') - .eq('features.enabled', true) - .eq('profile_id', id) - .eq('enabled', true); - - if (error) { - throw error; - } - - const features = data.map((feature: any) => feature.features?.key); + const data = await prisma.profileFeature.findMany({ + where: { + profileId: id as string, + enabled: true, + feature: { enabled: true } + }, + select: { + feature: { select: { key: true } } + } + }); + + const features = data.map((feature) => feature.feature.key); await redis.set(`features:${id}`, JSON.stringify(features)); return res diff --git a/apps/api/pages/api/feature/getVerified.ts b/apps/api/pages/api/feature/getVerified.ts index 27ddf363c09e..8c3cbf032de7 100644 --- a/apps/api/pages/api/feature/getVerified.ts +++ b/apps/api/pages/api/feature/getVerified.ts @@ -1,7 +1,7 @@ import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (_req: NextApiRequest, res: NextApiResponse) => { @@ -16,12 +16,9 @@ const handler = async (_req: NextApiRequest, res: NextApiResponse) => { .json({ success: true, cached: true, result: JSON.parse(cache) }); } - const client = createSupabaseClient(); - const { data, error } = await client.from('verified').select('*'); - - if (error) { - throw error; - } + const data = await prisma.verified.findMany({ + select: { id: true } + }); const ids = data.map((item) => item.id); await redis.set('verified', JSON.stringify(ids)); diff --git a/apps/api/utils/prisma.ts b/apps/api/utils/prisma.ts index f9ecc9d6804c..4e54f7a77ec7 100644 --- a/apps/api/utils/prisma.ts +++ b/apps/api/utils/prisma.ts @@ -1,4 +1,4 @@ -import { PrismaClient } from '@prisma/client/edge'; +import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); From 2e23ad447823f90d48a36984a179e48c7ab0f889 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:40:47 +0530 Subject: [PATCH 03/12] chore: migrate to prisma --- .../api/internal/feature/getAllFeatureFlags.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/apps/api/pages/api/internal/feature/getAllFeatureFlags.ts b/apps/api/pages/api/internal/feature/getAllFeatureFlags.ts index 266d9ce65af7..41bffe5deb74 100644 --- a/apps/api/pages/api/internal/feature/getAllFeatureFlags.ts +++ b/apps/api/pages/api/internal/feature/getAllFeatureFlags.ts @@ -1,20 +1,13 @@ import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (_req: NextApiRequest, res: NextApiResponse) => { try { - const client = createSupabaseClient(); - - const { data, error } = await client - .from('features') - .select('*') - .order('priority', { ascending: false }); - - if (error) { - throw error; - } + const data = await prisma.feature.findMany({ + orderBy: { priority: 'desc' } + }); return res .status(200) From 048f755eb3cada371d0de3685e2d6db5b4b6d65a Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:44:19 +0530 Subject: [PATCH 04/12] chore: migrate to prisma --- .../api/pages/api/preference/getHeyMemberNftStatus.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/api/pages/api/preference/getHeyMemberNftStatus.ts b/apps/api/pages/api/preference/getHeyMemberNftStatus.ts index caff5c5f9d69..fb3dce602bf3 100644 --- a/apps/api/pages/api/preference/getHeyMemberNftStatus.ts +++ b/apps/api/pages/api/preference/getHeyMemberNftStatus.ts @@ -2,7 +2,7 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (req: NextApiRequest, res: NextApiResponse) => { @@ -23,12 +23,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { .json({ success: true, cached: true, result: JSON.parse(cache) }); } - const client = createSupabaseClient(); - const { data } = await client - .from('membership-nft') - .select('*') - .eq('id', id) - .single(); + const data = await prisma.membershipNft.findUnique({ + where: { id: id as string } + }); await redis.set(`membership-nft:${id}`, JSON.stringify(data)); return res.status(200).setHeader('Cache-Control', CACHE_AGE).json({ From 1b25fedd2df560ad7642b554334572aaf46aa7d6 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:48:23 +0530 Subject: [PATCH 05/12] chore: migrate to prisma --- apps/api/pages/api/preference/getPreferences.ts | 11 ++++------- apps/api/pages/api/pro/getProEnabled.ts | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/apps/api/pages/api/preference/getPreferences.ts b/apps/api/pages/api/preference/getPreferences.ts index 3699702033ed..b5ac0a977134 100644 --- a/apps/api/pages/api/preference/getPreferences.ts +++ b/apps/api/pages/api/preference/getPreferences.ts @@ -2,7 +2,7 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (req: NextApiRequest, res: NextApiResponse) => { @@ -23,12 +23,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { .json({ success: true, cached: true, result: JSON.parse(cache) }); } - const client = createSupabaseClient(); - const { data } = await client - .from('preferences') - .select('*') - .eq('id', id) - .single(); + const data = await prisma.preference.findUnique({ + where: { id: id as string } + }); await redis.set(`preferences:${id}`, JSON.stringify(data)); return res.status(200).setHeader('Cache-Control', CACHE_AGE).json({ diff --git a/apps/api/pages/api/pro/getProEnabled.ts b/apps/api/pages/api/pro/getProEnabled.ts index 6d480de1e889..85c939d4e4e9 100644 --- a/apps/api/pages/api/pro/getProEnabled.ts +++ b/apps/api/pages/api/pro/getProEnabled.ts @@ -2,7 +2,7 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (req: NextApiRequest, res: NextApiResponse) => { @@ -27,12 +27,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { }); } - const client = createSupabaseClient(); - const { data } = await client - .from('pro') - .select('id') - .eq('profile_id', id) - .single(); + const data = await prisma.pro.findFirst({ + where: { profileId: id as string } + }); await redis.set(`pro:${id}`, JSON.stringify(data)); return res From e3ff43c23d592d8a608901d863fe53921c202734 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:53:33 +0530 Subject: [PATCH 06/12] chore: migrate to prisma --- .../api/pages/api/staff-pick/getStaffPicks.ts | 28 ++++++++----- .../utils/middlewares/validateIsGardener.ts | 40 +++++++++---------- apps/api/utils/middlewares/validateIsStaff.ts | 40 +++++++++---------- .../utils/middlewares/validateLensAccount.ts | 31 ++++++++------ 4 files changed, 76 insertions(+), 63 deletions(-) diff --git a/apps/api/pages/api/staff-pick/getStaffPicks.ts b/apps/api/pages/api/staff-pick/getStaffPicks.ts index 296a01770b03..2330d5f4741e 100644 --- a/apps/api/pages/api/staff-pick/getStaffPicks.ts +++ b/apps/api/pages/api/staff-pick/getStaffPicks.ts @@ -1,17 +1,27 @@ import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import createRedisClient from '@utils/createRedisClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; -const handler = async (req: NextApiRequest, res: NextApiResponse) => { +const handler = async (_req: NextApiRequest, res: NextApiResponse) => { try { - const client = createSupabaseClient(); - const { data } = await client - .from('staff-picks') - .select('*') - .neq('score', 0) - .order('score', { ascending: false }) - .limit(10); + const redis = createRedisClient(); + const cache = await redis.get('staff-picks'); + + if (cache) { + return res + .status(200) + .setHeader('Cache-Control', CACHE_AGE) + .json({ success: true, cached: true, result: JSON.parse(cache) }); + } + + const data = await prisma.staffPick.findMany({ + where: { score: { not: 0 } }, + orderBy: { score: 'desc' }, + take: 5 + }); + await redis.set('staff-picks', JSON.stringify(data)); return res .status(200) diff --git a/apps/api/utils/middlewares/validateIsGardener.ts b/apps/api/utils/middlewares/validateIsGardener.ts index b3321b37853c..647fd19fd37e 100644 --- a/apps/api/utils/middlewares/validateIsGardener.ts +++ b/apps/api/utils/middlewares/validateIsGardener.ts @@ -1,5 +1,5 @@ import parseJwt from '@hey/lib/parseJwt'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest } from 'next'; import { GARDENER_FEATURE_ID } from '../constants'; @@ -15,32 +15,30 @@ const validateIsGardener = async (request: NextApiRequest) => { return false; } - const accessToken = request.headers['x-access-token'] as string; + try { + const accessToken = request.headers['x-access-token'] as string; - if (!accessToken) { - return false; - } + if (!accessToken) { + return false; + } - const payload = parseJwt(accessToken); - const client = createSupabaseClient(); + const payload = parseJwt(accessToken); + const data = await prisma.profileFeature.findFirst({ + where: { + profileId: payload.id, + featureId: GARDENER_FEATURE_ID, + enabled: true + } + }); - const { data, error } = await client - .from('profile-features') - .select('profile_id, enabled') - .eq('profile_id', payload.id) - .eq('feature_id', GARDENER_FEATURE_ID) - .eq('enabled', true) - .single(); + if (data?.enabled) { + return true; + } - if (error) { + return false; + } catch { return false; } - - if (data.enabled) { - return true; - } - - return false; }; export default validateIsGardener; diff --git a/apps/api/utils/middlewares/validateIsStaff.ts b/apps/api/utils/middlewares/validateIsStaff.ts index 086250254204..71f9ccd34b54 100644 --- a/apps/api/utils/middlewares/validateIsStaff.ts +++ b/apps/api/utils/middlewares/validateIsStaff.ts @@ -1,5 +1,5 @@ import parseJwt from '@hey/lib/parseJwt'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest } from 'next'; import { STAFF_FEATURE_ID } from '../constants'; @@ -15,32 +15,30 @@ const validateIsStaff = async (request: NextApiRequest) => { return false; } - const accessToken = request.headers['x-access-token'] as string; + try { + const accessToken = request.headers['x-access-token'] as string; - if (!accessToken) { - return false; - } + if (!accessToken) { + return false; + } - const payload = parseJwt(accessToken); - const client = createSupabaseClient(); + const payload = parseJwt(accessToken); + const data = await prisma.profileFeature.findFirst({ + where: { + profileId: payload.id, + featureId: STAFF_FEATURE_ID, + enabled: true + } + }); - const { data, error } = await client - .from('profile-features') - .select('profile_id, enabled') - .eq('profile_id', payload.id) - .eq('feature_id', STAFF_FEATURE_ID) - .eq('enabled', true) - .single(); + if (data?.enabled) { + return true; + } - if (error) { + return false; + } catch { return false; } - - if (data.enabled) { - return true; - } - - return false; }; export default validateIsStaff; diff --git a/apps/api/utils/middlewares/validateLensAccount.ts b/apps/api/utils/middlewares/validateLensAccount.ts index 26e5d7ea89bc..3387b0d68d49 100644 --- a/apps/api/utils/middlewares/validateLensAccount.ts +++ b/apps/api/utils/middlewares/validateLensAccount.ts @@ -17,23 +17,30 @@ const validateLensAccount = async (request: NextApiRequest) => { } const isMainnet = network === 'mainnet'; - const lensResponse = await axios.post( - isMainnet ? LensEndpoint.Mainnet : LensEndpoint.Testnet, - { - query: ` + try { + const lensResponse = await axios.post( + isMainnet ? LensEndpoint.Mainnet : LensEndpoint.Testnet, + { + query: ` query Verify { verify(request: { accessToken: "${accessToken}" }) } ` - }, - { - headers: { 'Content-Type': 'application/json', 'User-agent': 'Hey.xyz' }, - withCredentials: true - } - ); + }, + { + headers: { + 'Content-Type': 'application/json', + 'User-agent': 'Hey.xyz' + }, + withCredentials: true + } + ); - if (!lensResponse.data.verify) { - return true; + if (!lensResponse.data.verify) { + return true; + } + } catch { + return false; } }; From 4b75bf7ac0bab157bd0c7a953bd0c7c38c44bb59 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:59:04 +0530 Subject: [PATCH 07/12] chore: migrate to prisma --- apps/api/db/schema.prisma | 3 +- .../api/pages/api/internal/pro/activatePro.ts | 28 ++++++------------- .../api/internal/pro/downgradeProfiles.ts | 14 +++------- .../api/internal/verified/updateVerified.ts | 23 +++------------ 4 files changed, 17 insertions(+), 51 deletions(-) diff --git a/apps/api/db/schema.prisma b/apps/api/db/schema.prisma index cf9b608fde74..3ccdf580f372 100644 --- a/apps/api/db/schema.prisma +++ b/apps/api/db/schema.prisma @@ -48,8 +48,7 @@ model Group { } model Pro { - id String @id @default(uuid()) - profileId String + profileId String @id hash String createdAt DateTime @default(now()) expiresAt DateTime? diff --git a/apps/api/pages/api/internal/pro/activatePro.ts b/apps/api/pages/api/internal/pro/activatePro.ts index 0f58689cbe5c..449e19161b2a 100644 --- a/apps/api/pages/api/internal/pro/activatePro.ts +++ b/apps/api/pages/api/internal/pro/activatePro.ts @@ -1,8 +1,8 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateIsStaff from '@utils/middlewares/validateIsStaff'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { boolean, object, string } from 'zod'; @@ -39,34 +39,22 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { try { const redis = createRedisClient(); - const client = createSupabaseClient(); if (enabled) { - const { error: upsertError } = await client.from('pro').upsert({ - profile_id: id, - hash: '0x00', - expires_at: '2100-01-01T00:00:00.000Z' + await prisma.pro.create({ + data: { + profileId: id, + hash: '0x00', + expiresAt: '2100-01-01T00:00:00.000Z' + } }); - - if (upsertError) { - throw upsertError; - } - // Delete the cache await redis.del(`pro:${id}`); return res.status(200).json({ success: true, enabled, trial }); } - const { error: deleteError } = await client - .from('pro') - .delete() - .match({ profile_id: id }); - - if (deleteError) { - throw deleteError; - } - + await prisma.pro.delete({ where: { profileId: id } }); // Delete the cache await redis.del(`pro:${id}`); diff --git a/apps/api/pages/api/internal/pro/downgradeProfiles.ts b/apps/api/pages/api/internal/pro/downgradeProfiles.ts index 0ecf9e644dec..df9e22fc1196 100644 --- a/apps/api/pages/api/internal/pro/downgradeProfiles.ts +++ b/apps/api/pages/api/internal/pro/downgradeProfiles.ts @@ -1,6 +1,6 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { object, string } from 'zod'; @@ -34,15 +34,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { } try { - const client = createSupabaseClient(); - const { error } = await client - .from('pro') - .delete() - .lte('expires_at', new Date().toISOString()); - - if (error) { - throw error; - } + await prisma.pro.deleteMany({ + where: { expiresAt: { lte: new Date().toISOString() } } + }); return res.status(200).json({ success: true }); } catch (error) { diff --git a/apps/api/pages/api/internal/verified/updateVerified.ts b/apps/api/pages/api/internal/verified/updateVerified.ts index e2485bd1c6cd..806ebdd7f09e 100644 --- a/apps/api/pages/api/internal/verified/updateVerified.ts +++ b/apps/api/pages/api/internal/verified/updateVerified.ts @@ -1,8 +1,8 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateIsStaff from '@utils/middlewares/validateIsStaff'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { boolean, object, string } from 'zod'; @@ -37,31 +37,16 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { try { const redis = createRedisClient(); - const client = createSupabaseClient(); - if (enabled) { - const { error: upsertError } = await client - .from('verified') - .upsert({ id }); - - if (upsertError) { - throw upsertError; - } + if (enabled) { + await prisma.verified.create({ data: { id } }); // Delete the cache await redis.del('verified'); return res.status(200).json({ success: true, enabled }); } - const { error: deleteError } = await client - .from('verified') - .delete() - .eq('id', id); - - if (deleteError) { - throw deleteError; - } - + await prisma.verified.delete({ where: { id } }); // Delete the cache await redis.del('verified'); From 52d064ff6a082da23d8f4a1891a0b38466f484c3 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:03:30 +0530 Subject: [PATCH 08/12] chore: migrate to prisma --- apps/api/pages/api/group/featuredGroups.ts | 23 ++++++++++++++++------ apps/api/pages/api/group/getGroup.ts | 23 +++++++++++++++------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/apps/api/pages/api/group/featuredGroups.ts b/apps/api/pages/api/group/featuredGroups.ts index 71a40c84be5f..ddb600e347c1 100644 --- a/apps/api/pages/api/group/featuredGroups.ts +++ b/apps/api/pages/api/group/featuredGroups.ts @@ -1,15 +1,26 @@ import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import createRedisClient from '@utils/createRedisClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (_req: NextApiRequest, res: NextApiResponse) => { try { - const client = createSupabaseClient(); - const { data } = await client - .from('groups') - .select('*') - .eq('featured', true); + const redis = createRedisClient(); + const cache = await redis.get('featured-groups'); + + if (cache) { + return res + .status(200) + .setHeader('Cache-Control', CACHE_AGE) + .json({ success: true, cached: true, result: JSON.parse(cache) }); + } + + const data = await prisma.group.findMany({ + where: { featured: true }, + orderBy: { createdAt: 'desc' } + }); + await redis.set('featured-groups', JSON.stringify(data)); return res .status(200) diff --git a/apps/api/pages/api/group/getGroup.ts b/apps/api/pages/api/group/getGroup.ts index 78e2e5b541df..6cbab14c5302 100644 --- a/apps/api/pages/api/group/getGroup.ts +++ b/apps/api/pages/api/group/getGroup.ts @@ -1,7 +1,8 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import { CACHE_AGE } from '@utils/constants'; -import createSupabaseClient from '@utils/createSupabaseClient'; +import createRedisClient from '@utils/createRedisClient'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (req: NextApiRequest, res: NextApiResponse) => { @@ -12,12 +13,20 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { } try { - const client = createSupabaseClient(); - const { data } = await client - .from('groups') - .select('*') - .eq('slug', slug) - .single(); + const redis = createRedisClient(); + const cache = await redis.get(`group:${slug}`); + + if (cache) { + return res + .status(200) + .setHeader('Cache-Control', CACHE_AGE) + .json({ success: true, cached: true, result: JSON.parse(cache) }); + } + + const data = await prisma.group.findUnique({ + where: { slug: slug as string } + }); + await redis.set(`group:${slug}`, JSON.stringify(data)); return res .status(200) From debacab13f7f28b92c975f7e5d540a552afcb0b9 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:08:44 +0530 Subject: [PATCH 09/12] chore: migrate to prisma --- .github/workflows/ci.yml | 2 +- apps/api/.env.example | 1 - apps/api/package.json | 1 - .../api/internal/feature/updateFeatureFlag.ts | 29 +-- .../internal/feature/updateGardenerMode.ts | 32 +-- .../api/internal/feature/updateStaffMode.ts | 32 +-- .../preference/updateHeyMemberNftStatus.ts | 16 +- .../pages/api/preference/updatePreferences.ts | 27 +- apps/api/utils/constants.ts | 1 - apps/api/utils/createSupabaseClient.ts | 14 -- packages/types/database.types.ts | 231 ------------------ packages/types/package.json | 1 - pnpm-lock.yaml | 152 ------------ 13 files changed, 52 insertions(+), 487 deletions(-) delete mode 100644 apps/api/utils/createSupabaseClient.ts delete mode 100644 packages/types/database.types.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0792bab529d0..b8851355403f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: - name: Run Tests 🧪 env: - SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} SECRET: ${{ secrets.SECRET }} EVER_ACCESS_KEY: ${{ secrets.EVER_ACCESS_KEY }} EVER_ACCESS_SECRET: ${{ secrets.EVER_ACCESS_SECRET }} diff --git a/apps/api/.env.example b/apps/api/.env.example index 1b7fc3c4ef72..775fe863811a 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -1,4 +1,3 @@ -SUPABASE_KEY="" DATABASE_URL="" CLICKHOUSE_PASSWORD="" SECRET="secret" diff --git a/apps/api/package.json b/apps/api/package.json index 3e9593df7538..7a395a9a3cab 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -25,7 +25,6 @@ "@hey/lib": "workspace:*", "@irys/sdk": "^0.0.4", "@prisma/client": "^5.6.0", - "@supabase/supabase-js": "^2.38.4", "axios": "^1.6.2", "fast-xml-parser": "^4.3.2", "ioredis": "^5.3.2", diff --git a/apps/api/pages/api/internal/feature/updateFeatureFlag.ts b/apps/api/pages/api/internal/feature/updateFeatureFlag.ts index d4bdab8a497a..d2cf5c2a4bc4 100644 --- a/apps/api/pages/api/internal/feature/updateFeatureFlag.ts +++ b/apps/api/pages/api/internal/feature/updateFeatureFlag.ts @@ -1,8 +1,8 @@ import { Errors } from '@hey/data/errors'; import allowCors from '@utils/allowCors'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateIsStaff from '@utils/middlewares/validateIsStaff'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { boolean, object, string } from 'zod'; @@ -39,33 +39,20 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { try { const redis = createRedisClient(); - const client = createSupabaseClient(); - if (enabled) { - const { error: upsertError } = await client - .from('profile-features') - .upsert({ feature_id: id, profile_id: profile_id }) - .select(); - - if (upsertError) { - throw upsertError; - } + if (enabled) { + await prisma.profileFeature.create({ + data: { featureId: id, profileId: profile_id } + }); // Delete the cache await redis.del(`features:${profile_id}`); return res.status(200).json({ success: true, enabled }); } - const { error: deleteError } = await client - .from('profile-features') - .delete() - .eq('feature_id', id) - .eq('profile_id', profile_id) - .select(); - - if (deleteError) { - throw deleteError; - } + await prisma.profileFeature.delete({ + where: { profileId_featureId: { featureId: id, profileId: profile_id } } + }); // Delete the cache await redis.del(`features:${profile_id}`); diff --git a/apps/api/pages/api/internal/feature/updateGardenerMode.ts b/apps/api/pages/api/internal/feature/updateGardenerMode.ts index aaef13bd7925..b5129386906b 100644 --- a/apps/api/pages/api/internal/feature/updateGardenerMode.ts +++ b/apps/api/pages/api/internal/feature/updateGardenerMode.ts @@ -3,8 +3,8 @@ import parseJwt from '@hey/lib/parseJwt'; import allowCors from '@utils/allowCors'; import { GARDENER_MODE_FEATURE_ID } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateIsGardener from '@utils/middlewares/validateIsGardener'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { boolean, object } from 'zod'; @@ -40,33 +40,25 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { const payload = parseJwt(accessToken); const profile_id = payload.id; const redis = createRedisClient(); - const client = createSupabaseClient(); if (enabled) { - const { error: upsertError } = await client - .from('profile-features') - .upsert({ feature_id: GARDENER_MODE_FEATURE_ID, profile_id }); - - if (upsertError) { - throw upsertError; - } - + await prisma.profileFeature.create({ + data: { featureId: GARDENER_MODE_FEATURE_ID, profileId: profile_id } + }); // Delete the cache await redis.del(`features:${profile_id}`); return res.status(200).json({ success: true, enabled }); } - const { error: deleteError } = await client - .from('profile-features') - .delete() - .eq('feature_id', GARDENER_MODE_FEATURE_ID) - .eq('profile_id', profile_id); - - if (deleteError) { - throw deleteError; - } - + await prisma.profileFeature.delete({ + where: { + profileId_featureId: { + featureId: GARDENER_MODE_FEATURE_ID, + profileId: profile_id + } + } + }); // Delete the cache await redis.del(`features:${profile_id}`); diff --git a/apps/api/pages/api/internal/feature/updateStaffMode.ts b/apps/api/pages/api/internal/feature/updateStaffMode.ts index 78d740a09c37..943508aace63 100644 --- a/apps/api/pages/api/internal/feature/updateStaffMode.ts +++ b/apps/api/pages/api/internal/feature/updateStaffMode.ts @@ -3,8 +3,8 @@ import parseJwt from '@hey/lib/parseJwt'; import allowCors from '@utils/allowCors'; import { STAFF_MODE_FEATURE_ID } from '@utils/constants'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateIsStaff from '@utils/middlewares/validateIsStaff'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { boolean, object } from 'zod'; @@ -40,33 +40,25 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { const payload = parseJwt(accessToken); const profile_id = payload.id; const redis = createRedisClient(); - const client = createSupabaseClient(); if (enabled) { - const { error: upsertError } = await client - .from('profile-features') - .upsert({ feature_id: STAFF_MODE_FEATURE_ID, profile_id }); - - if (upsertError) { - throw upsertError; - } - + await prisma.profileFeature.create({ + data: { featureId: STAFF_MODE_FEATURE_ID, profileId: profile_id } + }); // Delete the cache await redis.del(`features:${profile_id}`); return res.status(200).json({ success: true, enabled }); } - const { error: deleteError } = await client - .from('profile-features') - .delete() - .eq('feature_id', STAFF_MODE_FEATURE_ID) - .eq('profile_id', profile_id); - - if (deleteError) { - throw deleteError; - } - + await prisma.profileFeature.delete({ + where: { + profileId_featureId: { + featureId: STAFF_MODE_FEATURE_ID, + profileId: profile_id + } + } + }); // Delete the cache await redis.del(`features:${profile_id}`); diff --git a/apps/api/pages/api/preference/updateHeyMemberNftStatus.ts b/apps/api/pages/api/preference/updateHeyMemberNftStatus.ts index 35f27a9084b7..7ebc61175b64 100644 --- a/apps/api/pages/api/preference/updateHeyMemberNftStatus.ts +++ b/apps/api/pages/api/preference/updateHeyMemberNftStatus.ts @@ -2,8 +2,8 @@ import { Errors } from '@hey/data/errors'; import parseJwt from '@hey/lib/parseJwt'; import allowCors from '@utils/allowCors'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateLensAccount from '@utils/middlewares/validateLensAccount'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; const handler = async (req: NextApiRequest, res: NextApiResponse) => { @@ -18,16 +18,12 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { try { const payload = parseJwt(accessToken); const redis = createRedisClient(); - const client = createSupabaseClient(); - const { data, error } = await client - .from('membership-nft') - .upsert({ id: payload.evmAddress, dismissedOrMinted: true }) - .select() - .single(); - if (error) { - throw error; - } + const data = await prisma.membershipNft.upsert({ + where: { id: payload.id }, + update: { dismissedOrMinted: true }, + create: { id: payload.id, dismissedOrMinted: true } + }); // Delete the cache await redis.del(`membership-nft:${payload.evmAddress}`); diff --git a/apps/api/pages/api/preference/updatePreferences.ts b/apps/api/pages/api/preference/updatePreferences.ts index a5b7bcdb0faf..392d5690e5a3 100644 --- a/apps/api/pages/api/preference/updatePreferences.ts +++ b/apps/api/pages/api/preference/updatePreferences.ts @@ -2,8 +2,8 @@ import { Errors } from '@hey/data/errors'; import parseJwt from '@hey/lib/parseJwt'; import allowCors from '@utils/allowCors'; import createRedisClient from '@utils/createRedisClient'; -import createSupabaseClient from '@utils/createSupabaseClient'; import validateLensAccount from '@utils/middlewares/validateLensAccount'; +import prisma from '@utils/prisma'; import type { NextApiRequest, NextApiResponse } from 'next'; import { boolean, object, string } from 'zod'; @@ -44,20 +44,19 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { try { const payload = parseJwt(accessToken); const redis = createRedisClient(); - const client = createSupabaseClient(); - const { data, error } = await client - .from('preferences') - .upsert({ - id: payload.id, - is_pride: isPride, - high_signal_notification_filter: highSignalNotificationFilter - }) - .select() - .single(); - if (error) { - throw error; - } + const data = await prisma.preference.upsert({ + where: { id: payload.id }, + update: { + isPride: isPride, + highSignalNotificationFilter: highSignalNotificationFilter + }, + create: { + id: payload.id, + isPride: isPride, + highSignalNotificationFilter: highSignalNotificationFilter + } + }); // Delete the cache await redis.del(`preferences:${payload.id}`); diff --git a/apps/api/utils/constants.ts b/apps/api/utils/constants.ts index 5f85aa9b7ecc..0382d87bde56 100644 --- a/apps/api/utils/constants.ts +++ b/apps/api/utils/constants.ts @@ -1,5 +1,4 @@ // DB URLs -export const SUPABASE_URL = 'https://nberpnnqcqfnrzjpnisb.supabase.co'; export const CLICKHOUSE_URL = 'http://clickhouse.hey.xyz:8123'; // DB Feature IDs diff --git a/apps/api/utils/createSupabaseClient.ts b/apps/api/utils/createSupabaseClient.ts deleted file mode 100644 index 2aa835e01c79..000000000000 --- a/apps/api/utils/createSupabaseClient.ts +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-ignore -import type { Database } from '@hey/types/database.types'; -import { createClient } from '@supabase/supabase-js'; - -import { SUPABASE_URL } from './constants'; - -const createSupabaseClient = () => { - return createClient( - SUPABASE_URL, - process.env.SUPABASE_KEY as string - ); -}; - -export default createSupabaseClient; diff --git a/packages/types/database.types.ts b/packages/types/database.types.ts deleted file mode 100644 index e56d408baa0d..000000000000 --- a/packages/types/database.types.ts +++ /dev/null @@ -1,231 +0,0 @@ -export type Json = - | string - | number - | boolean - | null - | { [key: string]: Json | undefined } - | Json[]; - -export interface Database { - public: { - Tables: { - features: { - Row: { - description: string; - enabled: boolean; - id: string; - key: string; - name: string; - priority: number; - }; - Insert: { - description: string; - enabled?: boolean; - id?: string; - key: string; - name: string; - priority?: number; - }; - Update: { - description?: string; - enabled?: boolean; - id?: string; - key?: string; - name?: string; - priority?: number; - }; - Relationships: []; - }; - groups: { - Row: { - avatar: string; - contract: string | null; - created_at: string; - description: string; - discord: string | null; - featured: boolean; - id: string; - instagram: string | null; - lens: string | null; - name: string; - slug: string; - tags: string[] | null; - x: string | null; - }; - Insert: { - avatar: string; - contract?: string | null; - created_at?: string; - description: string; - discord?: string | null; - featured?: boolean; - id?: string; - instagram?: string | null; - lens?: string | null; - name: string; - slug: string; - tags?: string[] | null; - x?: string | null; - }; - Update: { - avatar?: string; - contract?: string | null; - created_at?: string; - description?: string; - discord?: string | null; - featured?: boolean; - id?: string; - instagram?: string | null; - lens?: string | null; - name?: string; - slug?: string; - tags?: string[] | null; - x?: string | null; - }; - Relationships: []; - }; - 'membership-nft': { - Row: { - dismissedOrMinted: boolean; - id: string; - }; - Insert: { - dismissedOrMinted?: boolean; - id: string; - }; - Update: { - dismissedOrMinted?: boolean; - id?: string; - }; - Relationships: []; - }; - preferences: { - Row: { - high_signal_notification_filter: boolean; - id: string; - is_pride: boolean; - }; - Insert: { - high_signal_notification_filter?: boolean; - id: string; - is_pride?: boolean; - }; - Update: { - high_signal_notification_filter?: boolean; - id?: string; - is_pride?: boolean; - }; - Relationships: []; - }; - pro: { - Row: { - created_at: string; - expires_at: string | null; - hash: string | null; - id: string; - profile_id: string; - }; - Insert: { - created_at?: string; - expires_at?: string | null; - hash?: string | null; - id?: string; - profile_id: string; - }; - Update: { - created_at?: string; - expires_at?: string | null; - hash?: string | null; - id?: string; - profile_id?: string; - }; - Relationships: []; - }; - 'profile-features': { - Row: { - created_at: string; - enabled: boolean; - feature_id: string; - profile_id: string; - }; - Insert: { - created_at?: string; - enabled?: boolean; - feature_id: string; - profile_id: string; - }; - Update: { - created_at?: string; - enabled?: boolean; - feature_id?: string; - profile_id?: string; - }; - Relationships: [ - { - foreignKeyName: 'profile-features_feature_id_fkey'; - columns: ['feature_id']; - isOneToOne: false; - referencedRelation: 'features'; - referencedColumns: ['id']; - } - ]; - }; - 'staff-picks': { - Row: { - created_at: string; - id: string; - picker_id: string; - score: number; - type: string; - }; - Insert: { - created_at?: string; - id: string; - picker_id: string; - score?: number; - type: string; - }; - Update: { - created_at?: string; - id?: string; - picker_id?: string; - score?: number; - type?: string; - }; - Relationships: [ - { - foreignKeyName: 'staff-picks_picker_id_fkey'; - columns: ['picker_id']; - isOneToOne: false; - referencedRelation: 'preferences'; - referencedColumns: ['id']; - } - ]; - }; - verified: { - Row: { - id: string; - }; - Insert: { - id: string; - }; - Update: { - id?: string; - }; - Relationships: []; - }; - }; - Views: { - [_ in never]: never; - }; - Functions: { - [_ in never]: never; - }; - Enums: { - [_ in never]: never; - }; - CompositeTypes: { - [_ in never]: never; - }; - }; -} diff --git a/packages/types/package.json b/packages/types/package.json index 8d8c5e58ba76..96c2ce84d2af 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -5,7 +5,6 @@ "license": "AGPL-3.0", "main": "index.ts", "scripts": { - "codegen": "supabase gen types typescript --project-id nberpnnqcqfnrzjpnisb > database.types.ts; pnpm lint:fix", "lint": "eslint . --ext .ts", "lint:fix": "eslint . --fix --ext .ts", "prettier": "prettier --check \"**/*.{js,ts,tsx,md}\" --cache", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be1de82dae90..640c0d0bf8f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,9 +44,6 @@ importers: '@prisma/client': specifier: ^5.6.0 version: 5.6.0(prisma@5.6.0) - '@supabase/supabase-js': - specifier: ^2.38.4 - version: 2.38.4 axios: specifier: ^1.6.2 version: 1.6.2(debug@4.3.4) @@ -5595,61 +5592,6 @@ packages: react: 18.2.0 dev: false - /@supabase/functions-js@2.1.5: - resolution: {integrity: sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw==} - dependencies: - '@supabase/node-fetch': 2.6.15 - dev: false - - /@supabase/gotrue-js@2.57.0: - resolution: {integrity: sha512-/CcAW40aPKgp9/w9WgXVUQFg1AOdvFR687ONOMjASPBuC6FsNbKlcXp4pc+rwKNtxyxDkBbR+x7zj/8g00r/Og==} - dependencies: - '@supabase/node-fetch': 2.6.15 - dev: false - - /@supabase/node-fetch@2.6.15: - resolution: {integrity: sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==} - engines: {node: 4.x || >=6.0.0} - dependencies: - whatwg-url: 5.0.0 - dev: false - - /@supabase/postgrest-js@1.8.6: - resolution: {integrity: sha512-iiEgF6o/pBumdFe/A2HSG/xx3L6ap7OO3IpTB2hsamNiH/gWb8ru4Z8bdwZjN4sQQttxgsIgZVMsNLkTOCOQhw==} - dependencies: - '@supabase/node-fetch': 2.6.15 - dev: false - - /@supabase/realtime-js@2.8.4: - resolution: {integrity: sha512-5C9slLTGikHnYmAnIBOaPogAgbcNY68vnIyE6GpqIKjHElVb6LIi4clwNcjHSj4z6szuvvzj8T/+ePEgGEGekw==} - dependencies: - '@supabase/node-fetch': 2.6.15 - '@types/phoenix': 1.6.4 - '@types/websocket': 1.0.9 - websocket: 1.0.34 - transitivePeerDependencies: - - supports-color - dev: false - - /@supabase/storage-js@2.5.4: - resolution: {integrity: sha512-yspHD19I9uQUgfTh0J94+/r/g6hnhdQmw6Y7OWqr/EbnL6uvicGV1i1UDkkmeUHqfF9Mbt2sLtuxRycYyKv2ew==} - dependencies: - '@supabase/node-fetch': 2.6.15 - dev: false - - /@supabase/supabase-js@2.38.4: - resolution: {integrity: sha512-bYwxm/GosvRqOMIv6YP7qUTZWi/trgHtDWUEZDEmyRHW24d0JYIb1GOt6RaO2hsWlecn88DAJIpjoNbprocgRA==} - dependencies: - '@supabase/functions-js': 2.1.5 - '@supabase/gotrue-js': 2.57.0 - '@supabase/node-fetch': 2.6.15 - '@supabase/postgrest-js': 1.8.6 - '@supabase/realtime-js': 2.8.4 - '@supabase/storage-js': 2.5.4 - transitivePeerDependencies: - - supports-color - dev: false - /@supercharge/promise-pool@3.1.0: resolution: {integrity: sha512-gB3NukbIcYzRtPoE6dx9svQYPodxvnfQlaaQd8N/z87E6WaMfRE7o5HwB+LZ+KeM0nsNAq1n4TmBtfz1VCUR+Q==} engines: {node: '>=8'} @@ -5875,10 +5817,6 @@ packages: resolution: {integrity: sha512-iclKEmOclXH2LGVkMkdal0+ffJphB3kbazakec96z1hW/CfJYmsZNFYLAmkpzePxKoKewXp2HSlsN6G4SG0b0g==} dev: true - /@types/phoenix@1.6.4: - resolution: {integrity: sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA==} - dev: false - /@types/prop-types@15.7.10: resolution: {integrity: sha512-mxSnDQxPqsZxmeShFH+uwQ4kO4gcJcGahjjMFeLbKE95IAZiiZyiEepGZjtXJ7hN/yfu0bu9xN2ajcU0JcxX6A==} @@ -5923,12 +5861,6 @@ packages: resolution: {integrity: sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==} dev: true - /@types/websocket@1.0.9: - resolution: {integrity: sha512-xrMBdqdKdlE+7L9Wg2PQblIkZGSgiMlEoP6UAaYKMHbbxqCJ6PV/pTZ2RcMcSSERurU2TtGbmO4lqpFOJd01ww==} - dependencies: - '@types/node': 20.9.2 - dev: false - /@types/ws@7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: @@ -7891,13 +7823,6 @@ packages: resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==} dev: false - /d@1.0.1: - resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} - dependencies: - es5-ext: 0.10.62 - type: 1.2.0 - dev: false - /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true @@ -7927,17 +7852,6 @@ packages: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} dev: true - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: false - /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -8334,24 +8248,6 @@ packages: is-symbol: 1.0.4 dev: true - /es5-ext@0.10.62: - resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} - engines: {node: '>=0.10'} - requiresBuild: true - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - next-tick: 1.1.0 - dev: false - - /es6-iterator@2.0.3: - resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - es6-symbol: 3.1.3 - dev: false - /es6-promise@4.2.8: resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} dev: false @@ -8362,13 +8258,6 @@ packages: es6-promise: 4.2.8 dev: false - /es6-symbol@3.1.3: - resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} - dependencies: - d: 1.0.1 - ext: 1.7.0 - dev: false - /esbuild@0.19.5: resolution: {integrity: sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==} engines: {node: '>=12'} @@ -8855,12 +8744,6 @@ packages: dev: false optional: true - /ext@1.7.0: - resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} - dependencies: - type: 2.7.2 - dev: false - /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: false @@ -10779,10 +10662,6 @@ packages: engines: {node: '>=4'} dev: false - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false - /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -10865,10 +10744,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /next-tick@1.1.0: - resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - dev: false - /next@14.0.3(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-AbYdRNfImBr3XGtvnwOxq8ekVCwbFTv/UJoLwmaX89nk9i051AEY4/HAWzU0YpaTDw8IofUpmuIlvzWF13jxIw==} engines: {node: '>=18.17.0'} @@ -13059,14 +12934,6 @@ packages: engines: {node: '>=8'} dev: true - /type@1.2.0: - resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} - dev: false - - /type@2.7.2: - resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - dev: false - /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} @@ -13737,20 +13604,6 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - /websocket@1.0.34: - resolution: {integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==} - engines: {node: '>=4.0.0'} - dependencies: - bufferutil: 4.0.8 - debug: 2.6.9 - es5-ext: 0.10.62 - typedarray-to-buffer: 3.1.5 - utf-8-validate: 5.0.10 - yaeti: 0.0.6 - transitivePeerDependencies: - - supports-color - dev: false - /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: @@ -13910,11 +13763,6 @@ packages: engines: {node: '>=10'} dev: true - /yaeti@0.0.6: - resolution: {integrity: sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==} - engines: {node: '>=0.10.32'} - dev: false - /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} dev: true From c9661b3b583cc60e8e1c96330378bbba14f9aee5 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:19:12 +0530 Subject: [PATCH 10/12] chore: update schema --- .../{20231119144606_ => 20231119154855_init}/migration.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename apps/api/db/migrations/{20231119144606_ => 20231119154855_init}/migration.sql (97%) diff --git a/apps/api/db/migrations/20231119144606_/migration.sql b/apps/api/db/migrations/20231119154855_init/migration.sql similarity index 97% rename from apps/api/db/migrations/20231119144606_/migration.sql rename to apps/api/db/migrations/20231119154855_init/migration.sql index 7ef27279c65a..0c81c80a01ca 100644 --- a/apps/api/db/migrations/20231119144606_/migration.sql +++ b/apps/api/db/migrations/20231119154855_init/migration.sql @@ -58,13 +58,12 @@ CREATE TABLE "Group" ( -- CreateTable CREATE TABLE "Pro" ( - "id" TEXT NOT NULL, "profileId" TEXT NOT NULL, "hash" TEXT NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "expiresAt" TIMESTAMP(3), - CONSTRAINT "Pro_pkey" PRIMARY KEY ("id") + CONSTRAINT "Pro_pkey" PRIMARY KEY ("profileId") ); -- CreateTable From d0a6590000b8c8f7e8aff6a98cf6a92449c2241d Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:25:32 +0530 Subject: [PATCH 11/12] fix: deploy --- apps/api/pages/api/feature/getFeatureFlags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/pages/api/feature/getFeatureFlags.ts b/apps/api/pages/api/feature/getFeatureFlags.ts index 40f30e5d5f32..659d09abec0a 100644 --- a/apps/api/pages/api/feature/getFeatureFlags.ts +++ b/apps/api/pages/api/feature/getFeatureFlags.ts @@ -34,7 +34,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { } }); - const features = data.map((feature) => feature.feature.key); + const features = data.map((feature: any) => feature.feature?.key); await redis.set(`features:${id}`, JSON.stringify(features)); return res From 6b26c53789fe0ac93de33dbb80f134c425e595de Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:27:48 +0530 Subject: [PATCH 12/12] fix: deploy --- apps/api/pages/api/feature/getVerified.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/pages/api/feature/getVerified.ts b/apps/api/pages/api/feature/getVerified.ts index 8c3cbf032de7..e8a937ce198d 100644 --- a/apps/api/pages/api/feature/getVerified.ts +++ b/apps/api/pages/api/feature/getVerified.ts @@ -20,7 +20,7 @@ const handler = async (_req: NextApiRequest, res: NextApiResponse) => { select: { id: true } }); - const ids = data.map((item) => item.id); + const ids = data.map((item: any) => item.id); await redis.set('verified', JSON.stringify(ids)); return res