feat: add cloudsave configuration w/ ludusavi search

This commit is contained in:
DecDuck
2025-06-11 22:14:21 +10:00
parent 5b27430ece
commit 95d6089453
20 changed files with 482 additions and 146 deletions

View File

@ -0,0 +1,69 @@
import { type } from "arktype";
import { CloudSaveType } from "~/prisma/client";
import { readDropValidatedBody, throwingArktype } from "~/server/arktype";
import aclManager from "~/server/internal/acls";
import prisma from "~/server/internal/db/database";
const UpdateEntry = type({
id: "string",
name: "string",
}).configure(throwingArktype);
export default defineEventHandler(async (h3) => {
const allowed = await aclManager.allowSystemACL(h3, [
"game:cloudsaves:update",
]);
if (!allowed) throw createError({ statusCode: 403 });
const body = await readDropValidatedBody(h3, UpdateEntry);
const entry = await prisma.ludusaviEntry.findUnique({
where: {
name: body.name,
},
include: {
entries: true,
},
});
if (!entry)
throw createError({
statusCode: 400,
statusMessage: "Invalid Ludusavi name",
});
const configuration = await prisma.cloudSaveConfiguration.upsert({
where: {
gameId: body.id,
},
create: {
gameId: body.id,
type: CloudSaveType.Ludusavi,
ludusaviEntryName: entry.name,
},
update: {
type: CloudSaveType.Ludusavi,
ludusaviEntryName: entry.name,
},
include: {
ludusaviEntry: {
include: {
entries: true,
},
},
},
});
await prisma.game.update({
where: {
id: body.id,
},
data: {
cloudSaveConfiguration: {
connect: {
gameId: body.id,
},
},
},
});
return configuration;
});

View File

@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
/* eslint-disable @typescript-eslint/no-extra-non-null-assertion */
import type { LudusaviEntry } from "~/prisma/client";
import aclManager from "~/server/internal/acls";
import prisma from "~/server/internal/db/database";
export default defineEventHandler(async (h3) => {
const allowed = await aclManager.allowSystemACL(h3, ["game:cloudsaves:read"]);
if (!allowed) throw createError({ statusCode: 403 });
const query = getQuery(h3);
const name = query.name?.toString()!!;
// Remove all non alphanumberical characters
const sanatisedName = name.replaceAll(/[^a-zA-Z\d\s:]/g, "");
const results = await prisma.$queryRaw`SELECT * FROM "LudusaviEntry" ORDER BY SIMILARITY(name, ${sanatisedName}) DESC LIMIT 20;`;
return results as Array<LudusaviEntry>;
});

View File

@ -30,6 +30,15 @@ export default defineEventHandler(async (h3) => {
delta: true,
},
},
cloudSaveConfiguration: {
include: {
ludusaviEntry: {
include: {
entries: true,
},
},
},
},
},
});