feat: use cloudflare kv

This commit is contained in:
uku 2024-10-26 11:50:41 +02:00
parent 8ae9355ec9
commit c2e36adc6a
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
8 changed files with 35 additions and 13 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -16,6 +16,7 @@
"leaflet-defaulticon-compatibility": "^0.1.2" "leaflet-defaulticon-compatibility": "^0.1.2"
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/workers-types": "^4.20241022.0",
"@sveltejs/adapter-cloudflare": "^4.7.4", "@sveltejs/adapter-cloudflare": "^4.7.4",
"@sveltejs/kit": "^2.7.3", "@sveltejs/kit": "^2.7.3",
"@sveltejs/vite-plugin-svelte": "^4.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.0",

6
src/app.d.ts vendored
View file

@ -6,7 +6,11 @@ declare global {
// interface Locals {} // interface Locals {}
// interface PageData {} // interface PageData {}
// interface PageState {} // interface PageState {}
// interface Platform {} interface Platform {
env?: {
TCL_GUESSR_KV: KVNamespace;
};
}
} }
} }

View file

@ -35,17 +35,22 @@ let lazyMetro: [GeoJSON.Feature, string][] | null = null;
let lazyTram: [GeoJSON.Feature, string][] | null = null; let lazyTram: [GeoJSON.Feature, string][] | null = null;
let lazyStops: GeoJSON.Feature[] | null = null; let lazyStops: GeoJSON.Feature[] | null = null;
const games: Record<string, GeoJSON.Feature> = {}; export async function createGame(stop: GeoJSON.Feature, kv: KVNamespace<string>): Promise<string> {
export function createGame(stop: GeoJSON.Feature): string {
const uuid = crypto.randomUUID(); const uuid = crypto.randomUUID();
games[uuid] = stop;
await kv.put(`game:${uuid}`, JSON.stringify(stop), { expirationTtl: 600 });
return uuid; return uuid;
} }
export function stopGame(uuid: string): GeoJSON.Feature | null { export async function stopGame(
const stop = games[uuid]; uuid: string,
delete games[uuid]; kv: KVNamespace<string>,
): Promise<GeoJSON.Feature | null> {
const stop: GeoJSON.Feature | null = await kv.get(`game:${uuid}`, "json");
if (stop) await kv.delete(`game:${uuid}`);
return stop; return stop;
} }

View file

@ -1,9 +1,13 @@
import { stopGame, type CheckData, type CheckResponse } from "$lib"; import { stopGame, type CheckData, type CheckResponse } from "$lib";
import { error } from "@sveltejs/kit";
import type { RequestHandler } from "./$types"; import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request }) => { export const POST: RequestHandler = async ({ request, platform }) => {
const kv = platform?.env?.TCL_GUESSR_KV;
if (!kv) return error(500, "could not connect to kv");
const data: CheckData = await request.json(); const data: CheckData = await request.json();
const stop = stopGame(data.gameId); const stop = await stopGame(data.gameId, kv);
if (stop) { if (stop) {
// GeoJSON data is LonLat, not LatLon // GeoJSON data is LonLat, not LatLon

View file

@ -2,7 +2,10 @@ import type { PageServerLoad } from "./$types";
import { createGame, getMetro, getStops, getTram, type GameData, type GameOptions } from "$lib"; import { createGame, getMetro, getStops, getTram, type GameData, type GameOptions } from "$lib";
import { error } from "@sveltejs/kit"; import { error } from "@sveltejs/kit";
export const load: PageServerLoad = async ({ fetch, url }) => { export const load: PageServerLoad = async ({ fetch, url, platform }) => {
const kv = platform?.env?.TCL_GUESSR_KV;
if (!kv) return error(500, "could not connect to kv");
const stops = await getStops(fetch); const stops = await getStops(fetch);
const mode = url.searchParams.get("mode"); const mode = url.searchParams.get("mode");
@ -40,7 +43,7 @@ export const load: PageServerLoad = async ({ fetch, url }) => {
return error(400, "could not select random stop"); return error(400, "could not select random stop");
} }
const gameId = createGame(randomStop); const gameId = await createGame(randomStop, kv);
const gameData: GameData = { const gameData: GameData = {
lines: options.mode === "easy" || options.mode === "hard" ? lineColors : [], lines: options.mode === "easy" || options.mode === "hard" ? lineColors : [],
stops: options.mode === "easy" ? crossingStops : [], stops: options.mode === "easy" ? crossingStops : [],

View file

@ -9,7 +9,8 @@
"skipLibCheck": true, "skipLibCheck": true,
"sourceMap": true, "sourceMap": true,
"strict": true, "strict": true,
"moduleResolution": "bundler" "moduleResolution": "bundler",
"types": ["@cloudflare/workers-types"]
} }
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files

View file

@ -1,3 +1,7 @@
name = "tcl-guessr" name = "tcl-guessr"
compatibility_date = "2024-09-25" compatibility_date = "2024-09-25"
pages_build_output_dir = ".svelte-kit/cloudflare" pages_build_output_dir = ".svelte-kit/cloudflare"
[[kv_namespaces]]
binding = "TCL_GUESSR_KV"
id = "b2d8980ac3a74a80854c35bf9569dbf8"