From eb064273edc1539cbc0a952b82b48275bbe23aa5 Mon Sep 17 00:00:00 2001 From: Daniel McCrystal Date: Fri, 8 Aug 2025 00:04:46 -0400 Subject: [PATCH] full e2e behavior, nice --- packages/client/src/app.tsx | 4 ++ packages/client/src/components/Game.tsx | 18 ++++-- .../client/src/routes/[game]/[instance].tsx | 1 - packages/client/src/routes/[game]/index.tsx | 21 +++--- packages/client/src/routes/index.tsx | 10 ++- packages/server/package.json | 4 +- packages/server/src/api.ts | 64 ++++++++++++++++++- packages/{client => server}/src/db/Games.ts | 0 .../{client => server}/src/db/Instances.ts | 0 packages/{client => server}/src/db/db.ts | 0 pnpm-lock.yaml | 22 +++++++ 11 files changed, 117 insertions(+), 27 deletions(-) rename packages/{client => server}/src/db/Games.ts (100%) rename packages/{client => server}/src/db/Instances.ts (100%) rename packages/{client => server}/src/db/db.ts (100%) diff --git a/packages/client/src/app.tsx b/packages/client/src/app.tsx index 47515c0..e6adc86 100644 --- a/packages/client/src/app.tsx +++ b/packages/client/src/app.tsx @@ -35,6 +35,10 @@ const App = () => ( path="/:game" component={lazy(() => import("./routes/[game]/index"))} /> + import("./routes/[game]/[instance]"))} + /> ); diff --git a/packages/client/src/components/Game.tsx b/packages/client/src/components/Game.tsx index 8c5eee4..5b15a02 100644 --- a/packages/client/src/components/Game.tsx +++ b/packages/client/src/components/Game.tsx @@ -1,6 +1,7 @@ import { Accessor, createContext, + createEffect, createResource, JSX, Show, @@ -11,7 +12,7 @@ import Hand from "./Hand"; import Pile from "./Pile"; import { GameState, newDeck, shuffle, Hand as THand } from "../types/cards"; import { createStore, produce, SetStoreFunction, Store } from "solid-js/store"; -import { getGameState, updateGameState } from "../db/Instances"; +import api from "../api"; export const GameContext = createContext<{ gameState: Accessor; @@ -19,17 +20,24 @@ export const GameContext = createContext<{ }>(); export default (props: { instanceId: number }) => { - const [gameState, { refetch }] = createResource(() => - getGameState(props.instanceId) + const [gameState, { refetch }] = createResource(() => + api.gameState[":gameId"] + .$get({ param: { gameId: props.instanceId.toString() } }) + .then((res) => res.json()) ); + const setGameState = (state: GameState) => - updateGameState(props.instanceId, state).then(refetch); + api.gameState[":gameId"] + .$put({ + param: { gameId: props.instanceId.toString() }, + json: state, + }) + .then(refetch); return (
{}} class="full column center" style={{ "row-gap": "20px", "font-size": "32px" }} > diff --git a/packages/client/src/routes/[game]/[instance].tsx b/packages/client/src/routes/[game]/[instance].tsx index cb9f6cc..4fbf143 100644 --- a/packages/client/src/routes/[game]/[instance].tsx +++ b/packages/client/src/routes/[game]/[instance].tsx @@ -2,7 +2,6 @@ import { A, useParams } from "@solidjs/router"; import { createEffect, createResource, Show, Suspense } from "solid-js"; import Game from "../../components/Game"; -import { getGameState } from "../../db/Instances"; export default () => { const params = useParams<{ game: string; instance: string }>(); diff --git a/packages/client/src/routes/[game]/index.tsx b/packages/client/src/routes/[game]/index.tsx index de0d87c..a3d6118 100644 --- a/packages/client/src/routes/[game]/index.tsx +++ b/packages/client/src/routes/[game]/index.tsx @@ -1,32 +1,27 @@ import { A, useParams } from "@solidjs/router"; import { createEffect, createResource, For, Suspense } from "solid-js"; -import * as Instance from "../../db/Instances"; +import api from "../../api"; export default () => { - const params = useParams<{ game: string }>(); + const param = useParams<{ game: string }>(); const [instances, { refetch }] = createResource( - () => params.game, - () => Instance.queryInstances(params.game) + () => param.game, + async () => + api.instances.$get({ query: param }).then((res) => res.json()) ); return (
-

{params.game}

- +

{param.game}

+
    {(instance) => (
  • - + {instance.id}
  • diff --git a/packages/client/src/routes/index.tsx b/packages/client/src/routes/index.tsx index ffe46ef..8dd4487 100644 --- a/packages/client/src/routes/index.tsx +++ b/packages/client/src/routes/index.tsx @@ -1,19 +1,17 @@ import { A } from "@solidjs/router"; import { createEffect, createResource, For } from "solid-js"; -import * as Games from "../db/Games"; import api from "../api"; export default () => { - const [ping] = createResource(async () => - api.ping.$get().then(async (res) => await res.text()) + const [games] = createResource(async () => + api.games.$get().then((res) => res.json()) ); return (
    - {ping()} - {/* + {(game) => {game.name}} - */} +
    ); }; diff --git a/packages/server/package.json b/packages/server/package.json index bdfd07c..83019b4 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -9,8 +9,10 @@ "start": "NODE_ENV=production bun run --port 5001 src/index.ts" }, "dependencies": { + "@hono/zod-validator": "^0.7.2", "@prisma/client": "6.13.0", - "hono": "^4.8.12" + "hono": "^4.8.12", + "zod": "^4.0.15" }, "devDependencies": { "@types/bun": "latest", diff --git a/packages/server/src/api.ts b/packages/server/src/api.ts index 70dcf7c..5e5a2da 100644 --- a/packages/server/src/api.ts +++ b/packages/server/src/api.ts @@ -1,6 +1,68 @@ import { Hono } from "hono"; +import { prisma } from "./db/db"; +import { zValidator } from "@hono/zod-validator"; +import { z } from "zod"; -const api = new Hono().get("/ping", (c) => c.text("pong")); +const api = new Hono() + .get("/ping", (c) => c.text("pong")) + .get("/games", async (c) => { + const games = await prisma.game.findMany(); + return c.json(games); + }) + + .get( + "/instances", + zValidator("query", z.object({ game: z.string() })), + async (c) => { + const { game } = c.req.valid("query"); + const instances = await prisma.instance.findMany({ + where: { + game: { + name: game, + }, + }, + select: { + id: true, + }, + }); + return c.json(instances); + } + ) + + .get( + "/gameState/:gameId", + zValidator("param", z.object({ gameId: z.string() })), + async (c) => { + const { gameId } = c.req.valid("param"); + const instance = await prisma.instance.findUnique({ + where: { + id: Number(gameId), + }, + }); + return c.json(instance?.gameState); + } + ) + + .put( + "/gameState/:gameId", + zValidator("param", z.object({ gameId: z.string() }), (result) => { + console.log(JSON.stringify(result, null, 2)); + }), + zValidator("json", z.any()), + async (c) => { + const { gameId } = c.req.valid("param"); + const gameState = c.req.valid("json"); + + await prisma.instance.update({ + data: { gameState }, + where: { + id: Number(gameId), + }, + }); + + return c.text("", 200); + } + ); export default api; export type ApiType = typeof api; diff --git a/packages/client/src/db/Games.ts b/packages/server/src/db/Games.ts similarity index 100% rename from packages/client/src/db/Games.ts rename to packages/server/src/db/Games.ts diff --git a/packages/client/src/db/Instances.ts b/packages/server/src/db/Instances.ts similarity index 100% rename from packages/client/src/db/Instances.ts rename to packages/server/src/db/Instances.ts diff --git a/packages/client/src/db/db.ts b/packages/server/src/db/db.ts similarity index 100% rename from packages/client/src/db/db.ts rename to packages/server/src/db/db.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2188d57..726c12b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,12 +29,18 @@ importers: packages/server: dependencies: + '@hono/zod-validator': + specifier: ^0.7.2 + version: 0.7.2(hono@4.8.12)(zod@4.0.15) '@prisma/client': specifier: 6.13.0 version: 6.13.0(prisma@6.13.0) hono: specifier: ^4.8.12 version: 4.8.12 + zod: + specifier: ^4.0.15 + version: 4.0.15 devDependencies: '@types/bun': specifier: latest @@ -289,6 +295,12 @@ packages: cpu: [x64] os: [win32] + '@hono/zod-validator@0.7.2': + resolution: {integrity: sha512-ub5eL/NeZ4eLZawu78JpW/J+dugDAYhwqUIdp9KYScI6PZECij4Hx4UsrthlEUutqDDhPwRI0MscUfNkvn/mqQ==} + peerDependencies: + hono: '>=3.9.0' + zod: ^3.25.0 || ^4.0.0 + '@jridgewell/gen-mapping@0.3.12': resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} @@ -958,6 +970,9 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + zod@4.0.15: + resolution: {integrity: sha512-2IVHb9h4Mt6+UXkyMs0XbfICUh1eUrlJJAOupBHUhLRnKkruawyDddYRCs0Eizt900ntIMk9/4RksYl+FgSpcQ==} + snapshots: '@ampproject/remapping@2.3.0': @@ -1154,6 +1169,11 @@ snapshots: '@esbuild/win32-x64@0.25.8': optional: true + '@hono/zod-validator@0.7.2(hono@4.8.12)(zod@4.0.15)': + dependencies: + hono: 4.8.12 + zod: 4.0.15 + '@jridgewell/gen-mapping@0.3.12': dependencies: '@jridgewell/sourcemap-codec': 1.5.4 @@ -1778,3 +1798,5 @@ snapshots: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 + + zod@4.0.15: {}