full e2e behavior, nice

This commit is contained in:
2025-08-08 00:04:46 -04:00
parent 9d4b17b762
commit eb064273ed
11 changed files with 117 additions and 27 deletions

View File

@@ -35,6 +35,10 @@ const App = () => (
path="/:game"
component={lazy(() => import("./routes/[game]/index"))}
/>
<Route
path="/:game/:instance"
component={lazy(() => import("./routes/[game]/[instance]"))}
/>
</Router>
);

View File

@@ -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<GameState | undefined>;
@@ -19,17 +20,24 @@ export const GameContext = createContext<{
}>();
export default (props: { instanceId: number }) => {
const [gameState, { refetch }] = createResource(() =>
getGameState(props.instanceId)
const [gameState, { refetch }] = createResource<GameState>(() =>
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 (
<GameContext.Provider value={{ gameState, setGameState }}>
<Show when={gameState() != undefined}>
<div
onClick={() => {}}
class="full column center"
style={{ "row-gap": "20px", "font-size": "32px" }}
>

View File

@@ -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 }>();

View File

@@ -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 (
<Suspense>
<div style={{ padding: "20px" }}>
<h1 style={{ margin: 0 }}>{params.game}</h1>
<button
onClick={() =>
Instance.createInstance(params.game).then(refetch)
}
>
New Game
</button>
<h1 style={{ margin: 0 }}>{param.game}</h1>
<button onClick={() => null}>New Game</button>
<ul>
<For each={instances() ?? []}>
{(instance) => (
<li>
<A href={`/${params.game}/${instance.id}`}>
<A href={`/${param.game}/${instance.id}`}>
{instance.id}
</A>
</li>

View File

@@ -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 (
<div style={{ padding: "20px" }}>
{ping()}
{/* <For each={games()}>
<For each={games()}>
{(game) => <A href={`/${game.name}`}>{game.name}</A>}
</For> */}
</For>
</div>
);
};

View File

@@ -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",

View File

@@ -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;

22
pnpm-lock.yaml generated
View File

@@ -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: {}