tokens fr

This commit is contained in:
2025-08-18 17:47:39 -04:00
parent 601e3660d3
commit 3f1635880a
11 changed files with 204 additions and 106 deletions

View File

@@ -60,7 +60,4 @@ const App = () => (
</Router>
);
// todo: fix this
(Cookies.get("token") == null ? api.whoami.post() : Promise.resolve()).then(
() => render(App, document.getElementById("app")!)
);
api.whoami.post().then(() => render(App, document.getElementById("app")!));

View File

@@ -0,0 +1,45 @@
/*
Warnings:
- The required column `token` was added to the `Human` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required.
*/
-- CreateTable
CREATE TABLE "_HumanToInstance" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
CONSTRAINT "_HumanToInstance_A_fkey" FOREIGN KEY ("A") REFERENCES "Human" ("key") ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "_HumanToInstance_B_fkey" FOREIGN KEY ("B") REFERENCES "Instance" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Human" (
"key" TEXT NOT NULL PRIMARY KEY,
"token" TEXT NOT NULL,
"name" TEXT NOT NULL DEFAULT '__name__',
"lastActive" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO "new_Human" ("key", "name") SELECT "key", "name" FROM "Human";
DROP TABLE "Human";
ALTER TABLE "new_Human" RENAME TO "Human";
CREATE UNIQUE INDEX "Human_token_key" ON "Human"("token");
CREATE TABLE "new_Instance" (
"id" TEXT NOT NULL PRIMARY KEY,
"createdByKey" TEXT NOT NULL,
"gameKey" TEXT NOT NULL,
"gameState" JSONB NOT NULL,
CONSTRAINT "Instance_gameKey_fkey" FOREIGN KEY ("gameKey") REFERENCES "Game" ("key") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Instance" ("createdByKey", "gameKey", "gameState", "id") SELECT "createdByKey", "gameKey", "gameState", "id" FROM "Instance";
DROP TABLE "Instance";
ALTER TABLE "new_Instance" RENAME TO "Instance";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
-- CreateIndex
CREATE UNIQUE INDEX "_HumanToInstance_AB_unique" ON "_HumanToInstance"("A", "B");
-- CreateIndex
CREATE INDEX "_HumanToInstance_B_index" ON "_HumanToInstance"("B");

View File

@@ -17,16 +17,21 @@ model Game {
}
model Human {
key String @id @default(cuid(2))
name String @default("")
Instance Instance[]
key String @id @default(cuid())
token String @unique @default(cuid())
name String @default("__name__")
lastActive DateTime @default(now())
playingInstances Instance[]
}
model Instance {
id String @id @default(cuid(2))
id String @id @default(cuid())
createdByKey String
createdBy Human @relation(fields: [createdByKey], references: [key])
gameKey String
game Game @relation(fields: [gameKey], references: [key])
gameState Json
players Human[]
game Game @relation(fields: [gameKey], references: [key])
gameState Json
}

View File

@@ -16,7 +16,10 @@
"@elysiajs/static": "^1.3.0",
"@games/shared": "workspace:*",
"@prisma/client": "6.13.0",
"dayjs": "^1.11.13",
"elysia": "^1.3.8",
"elysia-ip": "^1.0.10",
"elysia-rate-limit": "^4.4.0",
"object-hash": "^3.0.0"
},
"devDependencies": {

View File

@@ -1,16 +1,20 @@
import { prisma } from "./db/db";
import { Elysia, t } from "elysia";
import { Prisma } from "@prisma/client";
import { simpleApi } from "./games/simple";
import { human } from "./human";
import dayjs from "dayjs";
import db from "./db";
const api = new Elysia({ prefix: "/api" })
.post("/whoami", async ({ cookie: { token } }) => {
if (token.value == null) {
const newHuman = await prisma.human.create({
const newHuman = await db.human.create({
data: {},
});
token.value = newHuman.key;
token.set({
value: newHuman.token,
expires: dayjs().add(1, "year").toDate(),
httpOnly: true,
});
}
return token.value;
})
@@ -18,7 +22,7 @@ const api = new Elysia({ prefix: "/api" })
.post(
"/setName",
({ body: { name }, humanKey }) =>
prisma.human.update({
db.human.update({
where: {
key: humanKey,
},
@@ -33,16 +37,21 @@ const api = new Elysia({ prefix: "/api" })
}
)
.get("/profile", ({ humanKey }) =>
prisma.human.findFirst({ where: { key: humanKey } })
db.human.findFirst({ where: { key: humanKey } })
)
.get("/games", () => prisma.game.findMany())
.get("/games", () => [{ key: "simple", name: "simple" }])
.get("/instances", ({ query: { game } }) =>
prisma.instance.findMany({
.get("/instances", ({ query: { game }, humanKey }) =>
db.instance.findMany({
where: {
game: {
name: game,
},
players: {
some: {
key: humanKey,
},
},
},
select: {
id: true,

View File

@@ -2,4 +2,4 @@
import { PrismaClient } from "@prisma/client";
export const prisma = new PrismaClient();
export default new PrismaClient();

View File

@@ -1,4 +0,0 @@
"use server";
import { prisma } from "./db";
export const queryAll = async () => await prisma.game.findMany();

View File

@@ -1,25 +0,0 @@
"use server";
import { GameState, newDeck, shuffle } from "../types/cards";
import { prisma } from "./db";
export const queryInstances = async (gameName: string) =>
prisma.instance.findMany({ where: { game: { name: gameName } } });
export const createInstance = (gameName: string) =>
prisma.instance.create({
data: {
gameState: { deck: shuffle(newDeck()), hand: [] } as GameState,
game: { connect: { name: gameName } },
},
});
export const getGameState = (instanceId: number) =>
prisma.instance
.findUnique({ where: { id: instanceId } })
.then((i) => i?.gameState as GameState | undefined);
export const updateGameState = async (
instanceId: number,
gameState: GameState
) => prisma.instance.update({ where: { id: instanceId }, data: { gameState } });

View File

@@ -1,14 +1,7 @@
import {
Card,
Hand,
newDeck,
Pile,
shuffle,
vCard,
} from "../../../shared/cards";
import { Card, Hand, newDeck, Pile, shuffle, vCard } from "@games/shared/cards";
import { heq } from "@games/shared/utils";
import { Elysia, t } from "elysia";
import { prisma } from "../db/db";
import db from "../db";
import { human } from "../human";
// omniscient game state
@@ -114,18 +107,22 @@ export const resolveAction = (
export const simpleApi = new Elysia({ prefix: "/simple" })
.use(human)
.post("/newGame", ({ humanKey }) => {
return prisma.instance.create({
console.log("KEY", humanKey);
return db.instance.create({
data: {
gameState: newGame([humanKey]),
gameKey: "simple",
createdByKey: humanKey,
players: {
connect: [{ key: humanKey }],
},
},
});
})
.group("/:instanceId", (app) =>
app
.get("/", ({ params: { instanceId }, humanKey }) =>
prisma.instance
db.instance
.findUnique({
where: {
id: instanceId,
@@ -144,7 +141,7 @@ export const simpleApi = new Elysia({ prefix: "/simple" })
.post(
"/",
({ params: { instanceId }, body: { action }, humanKey }) =>
prisma.instance
db.instance
.findUniqueOrThrow({
where: {
id: instanceId,
@@ -156,7 +153,7 @@ export const simpleApi = new Elysia({ prefix: "/simple" })
humanKey,
action
);
await prisma.instance.update({
await db.instance.update({
data: { gameState: newState },
where: {
id: instanceId,

View File

@@ -1,8 +1,13 @@
import Elysia from "elysia";
import db from "./db";
export const human = new Elysia({ name: "human" })
.derive(async ({ cookie: { token }, status }) => {
const humanKey = token.value;
const humanKey = await db.human
.findUnique({
where: { token: token.value },
})
.then((human) => human?.key);
return humanKey != null ? { humanKey } : status(401);
})
.as("scoped");