Drizzle!
This commit is contained in:
parent
92b057993e
commit
047ebe9c8a
12 changed files with 999 additions and 176 deletions
12
drizzle.config.ts
Normal file
12
drizzle.config.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import type { Config } from "drizzle-kit";
|
||||||
|
import "dotenv/config";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
schema: "./src/server/schema.ts",
|
||||||
|
out: "./drizzle/generated",
|
||||||
|
driver: "mysql2",
|
||||||
|
breakpoints: true,
|
||||||
|
dbCredentials: {
|
||||||
|
connectionString: process.env.DATABASE_URL!,
|
||||||
|
},
|
||||||
|
} satisfies Config;
|
|
@ -15,6 +15,8 @@
|
||||||
"@ably-labs/react-hooks": "^2.1.1",
|
"@ably-labs/react-hooks": "^2.1.1",
|
||||||
"@auth/prisma-adapter": "^1.0.1",
|
"@auth/prisma-adapter": "^1.0.1",
|
||||||
"@clerk/nextjs": "^4.23.2",
|
"@clerk/nextjs": "^4.23.2",
|
||||||
|
"@paralleldrive/cuid2": "^2.2.2",
|
||||||
|
"@planetscale/database": "^1.10.0",
|
||||||
"@prisma/client": "5.1.1",
|
"@prisma/client": "5.1.1",
|
||||||
"@react-email/components": "^0.0.7",
|
"@react-email/components": "^0.0.7",
|
||||||
"@tanstack/react-query": "^4.32.6",
|
"@tanstack/react-query": "^4.32.6",
|
||||||
|
@ -27,6 +29,8 @@
|
||||||
"@upstash/redis": "^1.22.0",
|
"@upstash/redis": "^1.22.0",
|
||||||
"ably": "^1.2.43",
|
"ably": "^1.2.43",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"drizzle-orm": "^0.28.2",
|
||||||
"json2csv": "6.0.0-alpha.2",
|
"json2csv": "6.0.0-alpha.2",
|
||||||
"next": "^13.4.13",
|
"next": "^13.4.13",
|
||||||
"nextjs-cors": "^2.1.2",
|
"nextjs-cors": "^2.1.2",
|
||||||
|
@ -49,6 +53,7 @@
|
||||||
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
||||||
"@typescript-eslint/parser": "^6.3.0",
|
"@typescript-eslint/parser": "^6.3.0",
|
||||||
"daisyui": "^3.5.1",
|
"daisyui": "^3.5.1",
|
||||||
|
"drizzle-kit": "^0.19.12",
|
||||||
"eslint": "^8.46.0",
|
"eslint": "^8.46.0",
|
||||||
"eslint-config-next": "^13.4.13",
|
"eslint-config-next": "^13.4.13",
|
||||||
"prisma": "5.1.1",
|
"prisma": "5.1.1",
|
||||||
|
|
796
pnpm-lock.yaml
generated
796
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -10,9 +10,9 @@ export default createNextApiHandler({
|
||||||
onError:
|
onError:
|
||||||
env.NODE_ENV === "development"
|
env.NODE_ENV === "development"
|
||||||
? ({ path, error }) => {
|
? ({ path, error }) => {
|
||||||
console.error(
|
console.error(
|
||||||
`❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`,
|
`❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
|
@ -165,16 +165,16 @@ const RoomBody = ({}) => {
|
||||||
})
|
})
|
||||||
.concat({
|
.concat({
|
||||||
id: "LATEST",
|
id: "LATEST",
|
||||||
createdAt: new Date(),
|
created_at: new Date(),
|
||||||
userId: roomFromDb.userId,
|
userId: roomFromDb.userId,
|
||||||
roomId: roomFromDb.id,
|
roomId: roomFromDb.id,
|
||||||
scale: roomScale,
|
scale: roomScale,
|
||||||
votes: votesFromDb.map((vote) => {
|
votes: votesFromDb.map((vote) => {
|
||||||
return {
|
return {
|
||||||
name: vote.userId,
|
|
||||||
value: vote.value,
|
value: vote.value,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
room: roomFromDb,
|
||||||
roomName: roomFromDb.roomName,
|
roomName: roomFromDb.roomName,
|
||||||
storyName: storyNameText,
|
storyName: storyNameText,
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { z } from "zod";
|
||||||
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { fetchCache, setCache } from "~/server/redis";
|
import { fetchCache, setCache } from "~/server/redis";
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { rooms, votes } from "~/server/schema";
|
||||||
|
|
||||||
export const restRouter = createTRPCRouter({
|
export const restRouter = createTRPCRouter({
|
||||||
dbWarmer: publicProcedure
|
dbWarmer: publicProcedure
|
||||||
|
@ -13,7 +15,7 @@ export const restRouter = createTRPCRouter({
|
||||||
.query(async ({ ctx, input }) => {
|
.query(async ({ ctx, input }) => {
|
||||||
const isValidKey = await validateApiKey(input.key);
|
const isValidKey = await validateApiKey(input.key);
|
||||||
if (isValidKey) {
|
if (isValidKey) {
|
||||||
await ctx.prisma.vote.findMany();
|
await ctx.db.query.votes.findMany();
|
||||||
return "Toasted the DB";
|
return "Toasted the DB";
|
||||||
} else {
|
} else {
|
||||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||||
|
@ -30,7 +32,11 @@ export const restRouter = createTRPCRouter({
|
||||||
if (cachedResult) {
|
if (cachedResult) {
|
||||||
return cachedResult;
|
return cachedResult;
|
||||||
} else {
|
} else {
|
||||||
const votesCount = await ctx.prisma.vote.count();
|
const votesResult = (
|
||||||
|
await ctx.db.select({ count: sql<number>`count(*)` }).from(votes)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const votesCount = votesResult ? Number(votesResult.count) : 0;
|
||||||
|
|
||||||
await setCache(`kv_votecount`, votesCount);
|
await setCache(`kv_votecount`, votesCount);
|
||||||
|
|
||||||
|
@ -48,7 +54,11 @@ export const restRouter = createTRPCRouter({
|
||||||
if (cachedResult) {
|
if (cachedResult) {
|
||||||
return cachedResult;
|
return cachedResult;
|
||||||
} else {
|
} else {
|
||||||
const roomsCount = await ctx.prisma.room.count();
|
const roomsResult = (
|
||||||
|
await ctx.db.select({ count: sql<number>`count(*)` }).from(rooms)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const roomsCount = roomsResult ? Number(roomsResult.count) : 0;
|
||||||
|
|
||||||
await setCache(`kv_roomcount`, roomsCount);
|
await setCache(`kv_roomcount`, roomsCount);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,10 @@ import { publishToChannel } from "~/server/ably";
|
||||||
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
||||||
|
|
||||||
import { fetchCache, invalidateCache, setCache } from "~/server/redis";
|
import { fetchCache, invalidateCache, setCache } from "~/server/redis";
|
||||||
|
import { logs, rooms, votes } from "~/server/schema";
|
||||||
import { EventTypes } from "~/utils/types";
|
import { EventTypes } from "~/utils/types";
|
||||||
|
import { createId } from "@paralleldrive/cuid2";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
export const roomRouter = createTRPCRouter({
|
export const roomRouter = createTRPCRouter({
|
||||||
// Create
|
// Create
|
||||||
|
@ -14,18 +17,18 @@ export const roomRouter = createTRPCRouter({
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const room = await ctx.prisma.room.create({
|
const room = await ctx.db.insert(rooms).values({
|
||||||
data: {
|
id: createId(),
|
||||||
userId: ctx.auth.userId,
|
userId: ctx.auth.userId,
|
||||||
roomName: input.name,
|
roomName: input.name,
|
||||||
storyName: "First Story!",
|
storyName: "First Story!",
|
||||||
scale: "0.5,1,2,3,5,8",
|
scale: "0.5,1,2,3,5,8",
|
||||||
visible: false,
|
visible: false,
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const success = room.rowsAffected > 0;
|
||||||
if (room) {
|
if (room) {
|
||||||
await invalidateCache(`kv_roomcount`);
|
await invalidateCache(`kv_roomcount`);
|
||||||
console.log("PUBLISHED TO ", `kv_roomlist_${ctx.auth.userId}`);
|
|
||||||
await invalidateCache(`kv_roomlist_${ctx.auth.userId}`);
|
await invalidateCache(`kv_roomlist_${ctx.auth.userId}`);
|
||||||
|
|
||||||
await publishToChannel(
|
await publishToChannel(
|
||||||
|
@ -40,26 +43,26 @@ export const roomRouter = createTRPCRouter({
|
||||||
JSON.stringify(room)
|
JSON.stringify(room)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// happy path
|
return success;
|
||||||
return !!room;
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Get One
|
// Get One
|
||||||
get: protectedProcedure
|
get: protectedProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.query(({ ctx, input }) => {
|
.query(({ ctx, input }) => {
|
||||||
return ctx.prisma.room.findUnique({
|
return ctx.db.query.rooms.findFirst({
|
||||||
where: {
|
where: eq(rooms.id, input.id),
|
||||||
id: input.id,
|
with: {
|
||||||
},
|
logs: {
|
||||||
select: {
|
with: {
|
||||||
id: true,
|
room: true,
|
||||||
userId: true,
|
},
|
||||||
logs: true,
|
},
|
||||||
roomName: true,
|
votes: {
|
||||||
storyName: true,
|
with: {
|
||||||
visible: true,
|
room: true,
|
||||||
scale: true,
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
@ -77,15 +80,8 @@ export const roomRouter = createTRPCRouter({
|
||||||
if (cachedResult) {
|
if (cachedResult) {
|
||||||
return cachedResult;
|
return cachedResult;
|
||||||
} else {
|
} else {
|
||||||
const roomList = await ctx.prisma.room.findMany({
|
const roomList = await ctx.db.query.rooms.findMany({
|
||||||
where: {
|
where: eq(rooms.userId, ctx.auth.userId),
|
||||||
userId: ctx.auth.userId,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
createdAt: true,
|
|
||||||
roomName: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await setCache(`kv_roomlist_${ctx.auth.userId}`, roomList);
|
await setCache(`kv_roomlist_${ctx.auth.userId}`, roomList);
|
||||||
|
@ -109,98 +105,76 @@ export const roomRouter = createTRPCRouter({
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
if (input.reset) {
|
if (input.reset) {
|
||||||
if (input.log) {
|
if (input.log) {
|
||||||
const oldRoom = await ctx.prisma.room.findUnique({
|
const oldRoom = await ctx.db.query.rooms.findFirst({
|
||||||
where: {
|
where: eq(rooms.id, input.roomId),
|
||||||
id: input.roomId,
|
with: {
|
||||||
},
|
votes: true,
|
||||||
select: {
|
logs: true,
|
||||||
roomName: true,
|
|
||||||
storyName: true,
|
|
||||||
scale: true,
|
|
||||||
votes: {
|
|
||||||
select: {
|
|
||||||
userId: true,
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
oldRoom &&
|
oldRoom &&
|
||||||
(await ctx.prisma.log.create({
|
(await ctx.db.insert(logs).values({
|
||||||
data: {
|
id: createId(),
|
||||||
userId: ctx.auth.userId,
|
userId: ctx.auth.userId,
|
||||||
roomId: input.roomId,
|
roomId: input.roomId,
|
||||||
scale: oldRoom.scale,
|
scale: oldRoom.scale,
|
||||||
votes: oldRoom.votes.map((vote) => {
|
votes: oldRoom.votes.map((vote) => {
|
||||||
return {
|
return {
|
||||||
name: vote.userId,
|
name: vote.userId,
|
||||||
value: vote.value,
|
value: vote.value,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
roomName: oldRoom.roomName,
|
roomName: oldRoom.roomName,
|
||||||
storyName: oldRoom.storyName,
|
storyName: oldRoom.storyName,
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
await ctx.prisma.vote.deleteMany({
|
await ctx.db.delete(votes).where(eq(votes.roomId, input.roomId));
|
||||||
where: {
|
|
||||||
roomId: input.roomId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
await invalidateCache(`kv_votes_${input.roomId}`);
|
await invalidateCache(`kv_votes_${input.roomId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newRoom = await ctx.prisma.room.update({
|
const newRoom = await ctx.db
|
||||||
where: {
|
.update(rooms)
|
||||||
id: input.roomId,
|
.set({
|
||||||
},
|
|
||||||
data: {
|
|
||||||
storyName: input.name,
|
storyName: input.name,
|
||||||
userId: ctx.auth.userId,
|
userId: ctx.auth.userId,
|
||||||
visible: input.visible,
|
visible: input.visible,
|
||||||
scale: [...new Set(input.scale.split(","))]
|
scale: [...new Set(input.scale.split(","))]
|
||||||
.filter((item) => item !== "")
|
.filter((item) => item !== "")
|
||||||
.toString(),
|
.toString(),
|
||||||
},
|
})
|
||||||
select: {
|
.where(eq(rooms.id, input.roomId));
|
||||||
id: true,
|
|
||||||
roomName: true,
|
|
||||||
storyName: true,
|
|
||||||
visible: true,
|
|
||||||
scale: true,
|
|
||||||
votes: {
|
|
||||||
select: {
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (newRoom) {
|
const success = newRoom.rowsAffected > 0;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
await publishToChannel(
|
await publishToChannel(
|
||||||
`${newRoom.id}`,
|
`${input.roomId}`,
|
||||||
EventTypes.ROOM_UPDATE,
|
EventTypes.ROOM_UPDATE,
|
||||||
JSON.stringify(newRoom)
|
JSON.stringify(newRoom)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!newRoom;
|
return success;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Delete One
|
// Delete One
|
||||||
delete: protectedProcedure
|
delete: protectedProcedure
|
||||||
.input(z.object({ id: z.string() }))
|
.input(z.object({ id: z.string() }))
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const deletedRoom = await ctx.prisma.room.delete({
|
const deletedRoom = await ctx.db
|
||||||
where: {
|
.delete(rooms)
|
||||||
id: input.id,
|
.where(eq(rooms.id, input.id));
|
||||||
},
|
|
||||||
});
|
const success = deletedRoom.rowsAffected > 0;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
await ctx.db.delete(votes).where(eq(votes.roomId, input.id));
|
||||||
|
|
||||||
|
await ctx.db.delete(logs).where(eq(logs.roomId, input.id));
|
||||||
|
|
||||||
if (deletedRoom) {
|
|
||||||
await invalidateCache(`kv_roomcount`);
|
await invalidateCache(`kv_roomcount`);
|
||||||
await invalidateCache(`kv_votecount`);
|
await invalidateCache(`kv_votecount`);
|
||||||
await invalidateCache(`kv_roomlist_${ctx.auth.userId}`);
|
await invalidateCache(`kv_roomlist_${ctx.auth.userId}`);
|
||||||
|
@ -212,7 +186,7 @@ export const roomRouter = createTRPCRouter({
|
||||||
);
|
);
|
||||||
|
|
||||||
await publishToChannel(
|
await publishToChannel(
|
||||||
`${deletedRoom.id}`,
|
`${input.id}`,
|
||||||
EventTypes.ROOM_UPDATE,
|
EventTypes.ROOM_UPDATE,
|
||||||
JSON.stringify(deletedRoom)
|
JSON.stringify(deletedRoom)
|
||||||
);
|
);
|
||||||
|
@ -224,6 +198,6 @@ export const roomRouter = createTRPCRouter({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!deletedRoom;
|
return success;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { publishToChannel } from "~/server/ably";
|
import { publishToChannel } from "~/server/ably";
|
||||||
|
|
||||||
import type { Room } from "@prisma/client";
|
|
||||||
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
||||||
import { fetchCache, invalidateCache, setCache } from "~/server/redis";
|
import { fetchCache, invalidateCache, setCache } from "~/server/redis";
|
||||||
import { EventTypes } from "~/utils/types";
|
import { EventTypes } from "~/utils/types";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { votes } from "~/server/schema";
|
||||||
|
import { createId } from "@paralleldrive/cuid2";
|
||||||
|
|
||||||
export const voteRouter = createTRPCRouter({
|
export const voteRouter = createTRPCRouter({
|
||||||
getAllByRoomId: protectedProcedure
|
getAllByRoomId: protectedProcedure
|
||||||
|
@ -12,10 +14,9 @@ export const voteRouter = createTRPCRouter({
|
||||||
.query(async ({ ctx, input }) => {
|
.query(async ({ ctx, input }) => {
|
||||||
const cachedResult = await fetchCache<
|
const cachedResult = await fetchCache<
|
||||||
{
|
{
|
||||||
value: string;
|
|
||||||
room: Room;
|
|
||||||
id: string;
|
id: string;
|
||||||
createdAt: Date;
|
value: string;
|
||||||
|
created_at: Date;
|
||||||
userId: string;
|
userId: string;
|
||||||
roomId: string;
|
roomId: string;
|
||||||
}[]
|
}[]
|
||||||
|
@ -24,18 +25,8 @@ export const voteRouter = createTRPCRouter({
|
||||||
if (cachedResult) {
|
if (cachedResult) {
|
||||||
return cachedResult;
|
return cachedResult;
|
||||||
} else {
|
} else {
|
||||||
const votesByRoomId = await ctx.prisma.vote.findMany({
|
const votesByRoomId = await ctx.db.query.votes.findMany({
|
||||||
where: {
|
where: eq(votes.roomId, input.roomId),
|
||||||
roomId: input.roomId,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
createdAt: true,
|
|
||||||
room: true,
|
|
||||||
roomId: true,
|
|
||||||
userId: true,
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await setCache(`kv_votes_${input.roomId}`, votesByRoomId);
|
await setCache(`kv_votes_${input.roomId}`, votesByRoomId);
|
||||||
|
@ -46,37 +37,30 @@ export const voteRouter = createTRPCRouter({
|
||||||
set: protectedProcedure
|
set: protectedProcedure
|
||||||
.input(z.object({ value: z.string(), roomId: z.string() }))
|
.input(z.object({ value: z.string(), roomId: z.string() }))
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
const vote = await ctx.prisma.vote.upsert({
|
const vote = await ctx.db
|
||||||
where: {
|
.insert(votes)
|
||||||
userId_roomId: {
|
.values({
|
||||||
roomId: input.roomId,
|
id: createId(),
|
||||||
|
value: input.value,
|
||||||
|
userId: ctx.auth.userId,
|
||||||
|
roomId: input.roomId,
|
||||||
|
})
|
||||||
|
.onDuplicateKeyUpdate({
|
||||||
|
set: {
|
||||||
|
value: input.value,
|
||||||
userId: ctx.auth.userId,
|
userId: ctx.auth.userId,
|
||||||
|
roomId: input.roomId,
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
create: {
|
|
||||||
value: input.value,
|
|
||||||
userId: ctx.auth.userId,
|
|
||||||
roomId: input.roomId,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
value: input.value,
|
|
||||||
userId: ctx.auth.userId,
|
|
||||||
roomId: input.roomId,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
value: true,
|
|
||||||
userId: true,
|
|
||||||
roomId: true,
|
|
||||||
id: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (vote) {
|
const success = vote.rowsAffected > 0;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
await invalidateCache(`kv_votecount`);
|
await invalidateCache(`kv_votecount`);
|
||||||
await invalidateCache(`kv_votes_${input.roomId}`);
|
await invalidateCache(`kv_votes_${input.roomId}`);
|
||||||
|
|
||||||
await publishToChannel(
|
await publishToChannel(
|
||||||
`${vote.roomId}`,
|
`${input.roomId}`,
|
||||||
EventTypes.VOTE_UPDATE,
|
EventTypes.VOTE_UPDATE,
|
||||||
input.value
|
input.value
|
||||||
);
|
);
|
||||||
|
@ -84,10 +68,10 @@ export const voteRouter = createTRPCRouter({
|
||||||
await publishToChannel(
|
await publishToChannel(
|
||||||
`stats`,
|
`stats`,
|
||||||
EventTypes.STATS_UPDATE,
|
EventTypes.STATS_UPDATE,
|
||||||
JSON.stringify(vote)
|
JSON.stringify(success)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!vote;
|
return success;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,7 @@ import type {
|
||||||
SignedOutAuthObject,
|
SignedOutAuthObject,
|
||||||
} from "@clerk/nextjs/api";
|
} from "@clerk/nextjs/api";
|
||||||
|
|
||||||
import { prisma } from "../db";
|
import { db } from "../db";
|
||||||
|
|
||||||
interface AuthContext {
|
interface AuthContext {
|
||||||
auth: SignedInAuthObject | SignedOutAuthObject;
|
auth: SignedInAuthObject | SignedOutAuthObject;
|
||||||
|
@ -40,7 +40,7 @@ interface AuthContext {
|
||||||
const createInnerTRPCContext = ({ auth }: AuthContext) => {
|
const createInnerTRPCContext = ({ auth }: AuthContext) => {
|
||||||
return {
|
return {
|
||||||
auth,
|
auth,
|
||||||
prisma,
|
db,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ export const createTRPCContext = (opts: CreateNextContextOptions) => {
|
||||||
*/
|
*/
|
||||||
import { initTRPC, TRPCError } from "@trpc/server";
|
import { initTRPC, TRPCError } from "@trpc/server";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
import { OpenApiMeta } from "trpc-openapi";
|
import type { OpenApiMeta } from "trpc-openapi";
|
||||||
|
|
||||||
const t = initTRPC
|
const t = initTRPC
|
||||||
.context<typeof createTRPCContext>()
|
.context<typeof createTRPCContext>()
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import { PrismaClient } from "@prisma/client";
|
import { drizzle } from "drizzle-orm/planetscale-serverless";
|
||||||
|
import { connect } from "@planetscale/database";
|
||||||
import { env } from "~/env.mjs";
|
import { env } from "~/env.mjs";
|
||||||
|
import * as schema from "~/server/schema";
|
||||||
|
|
||||||
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
|
// create the connection
|
||||||
|
const connection = connect({
|
||||||
|
url: env.DATABASE_URL,
|
||||||
|
});
|
||||||
|
|
||||||
export const prisma =
|
export const db = drizzle(connection, { schema });
|
||||||
globalForPrisma.prisma ||
|
|
||||||
new PrismaClient({
|
|
||||||
log:
|
|
||||||
env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
|
|
||||||
});
|
|
||||||
|
|
||||||
if (env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
import { Redis } from "@upstash/redis";
|
import { Redis } from "@upstash/redis";
|
||||||
import https from "https";
|
|
||||||
import { env } from "~/env.mjs";
|
import { env } from "~/env.mjs";
|
||||||
|
|
||||||
export const redis = Redis.fromEnv({
|
export const redis = Redis.fromEnv();
|
||||||
agent: new https.Agent({ keepAlive: true }),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const setCache = async <T>(key: string, value: T) => {
|
export const setCache = async <T>(key: string, value: T) => {
|
||||||
try {
|
try {
|
||||||
console.log("KEY: ", key);
|
|
||||||
await redis.set(`${env.APP_ENV}_${key}`, value, {
|
await redis.set(`${env.APP_ENV}_${key}`, value, {
|
||||||
ex: Number(env.UPSTASH_REDIS_EXPIRY_SECONDS),
|
ex: Number(env.UPSTASH_REDIS_EXPIRY_SECONDS),
|
||||||
});
|
});
|
||||||
|
@ -21,14 +17,8 @@ export const setCache = async <T>(key: string, value: T) => {
|
||||||
export const fetchCache = async <T>(key: string) => {
|
export const fetchCache = async <T>(key: string) => {
|
||||||
try {
|
try {
|
||||||
const result = await redis.get(`${env.APP_ENV}_${key}`);
|
const result = await redis.get(`${env.APP_ENV}_${key}`);
|
||||||
if (result) {
|
|
||||||
console.log("CACHE HIT");
|
|
||||||
} else {
|
|
||||||
console.log("CACHE MISS");
|
|
||||||
}
|
|
||||||
return result as T;
|
return result as T;
|
||||||
} catch {
|
} catch {
|
||||||
console.log("CACHE ERROR");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
65
src/server/schema.ts
Normal file
65
src/server/schema.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import {
|
||||||
|
timestamp,
|
||||||
|
mysqlTable,
|
||||||
|
varchar,
|
||||||
|
boolean,
|
||||||
|
json,
|
||||||
|
} from "drizzle-orm/mysql-core";
|
||||||
|
import { relations } from "drizzle-orm";
|
||||||
|
|
||||||
|
export const rooms = mysqlTable("Room", {
|
||||||
|
id: varchar("id", { length: 255 }).notNull().primaryKey(),
|
||||||
|
created_at: timestamp("created_at", {
|
||||||
|
mode: "date",
|
||||||
|
fsp: 3,
|
||||||
|
}).defaultNow(),
|
||||||
|
userId: varchar("userId", { length: 255 }).notNull(),
|
||||||
|
roomName: varchar("roomName", { length: 255 }),
|
||||||
|
storyName: varchar("storyName", { length: 255 }),
|
||||||
|
visible: boolean("visible").default(false).notNull(),
|
||||||
|
scale: varchar("scale", { length: 255 }).default("0.5,1,2,3,5").notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const roomsRelations = relations(rooms, ({ many }) => ({
|
||||||
|
votes: many(votes),
|
||||||
|
logs: many(logs),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const votes = mysqlTable("Vote", {
|
||||||
|
id: varchar("id", { length: 255 }).notNull().primaryKey(),
|
||||||
|
created_at: timestamp("created_at", {
|
||||||
|
mode: "date",
|
||||||
|
fsp: 3,
|
||||||
|
}).defaultNow(),
|
||||||
|
userId: varchar("userId", { length: 255 }).notNull(),
|
||||||
|
roomId: varchar("roomId", { length: 255 }).notNull(),
|
||||||
|
value: varchar("value", { length: 255 }).notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const votesRelations = relations(votes, ({ one }) => ({
|
||||||
|
room: one(rooms, {
|
||||||
|
fields: [votes.roomId],
|
||||||
|
references: [rooms.id],
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const logs = mysqlTable("Log", {
|
||||||
|
id: varchar("id", { length: 255 }).notNull().primaryKey(),
|
||||||
|
created_at: timestamp("created_at", {
|
||||||
|
mode: "date",
|
||||||
|
fsp: 3,
|
||||||
|
}).defaultNow(),
|
||||||
|
userId: varchar("userId", { length: 255 }).notNull(),
|
||||||
|
roomId: varchar("roomId", { length: 255 }).notNull(),
|
||||||
|
scale: varchar("scale", { length: 255 }),
|
||||||
|
votes: json("votes"),
|
||||||
|
roomName: varchar("roomName", { length: 255 }),
|
||||||
|
storyName: varchar("storyName", { length: 255 }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const logsRelations = relations(logs, ({ one }) => ({
|
||||||
|
room: one(rooms, {
|
||||||
|
fields: [logs.roomId],
|
||||||
|
references: [rooms.id],
|
||||||
|
}),
|
||||||
|
}));
|
Loading…
Add table
Reference in a new issue