feat: add ludusavi metadata import into database

WARNING: includes debug route
This commit is contained in:
DecDuck
2025-06-03 17:27:35 +10:00
parent 1bfdd73e4c
commit 951a741f3e
7 changed files with 217 additions and 0 deletions

32
server/routes/ludusavi.ts Normal file
View File

@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
/* eslint-disable @typescript-eslint/no-extra-non-null-assertion */
import prisma from "../internal/db/database";
import { parsePlatform } from "../internal/utils/parseplatform";
import tsquery from "pg-tsquery";
export default defineEventHandler(async (h3) => {
const query = getQuery(h3);
const name = query.name?.toString()!!;
const platform = parsePlatform(query.platform?.toString()!!)!!;
const parser = tsquery({});
return await prisma.ludusaviEntry.findMany({
orderBy: {
_relevance: {
fields: ["name"],
search: parser(name),
sort: "desc",
},
},
include: {
entries: {
where: {
platform,
},
},
},
take: 20,
});
});

133
server/tasks/ludusavi.ts Normal file
View File

@ -0,0 +1,133 @@
import yaml from "js-yaml";
import prisma from "../internal/db/database";
import { Platform } from "~/prisma/client";
import type { LudusaviPlatformEntryCreateOrConnectWithoutLudusaviEntryInput } from "~/prisma/client/models";
type ConnectOrCreateShorthand =
LudusaviPlatformEntryCreateOrConnectWithoutLudusaviEntryInput;
type LudusaviModel = {
[key: string]: {
files?: {
[key: string]: {
tags?: Array<string>;
when?: Array<{ os?: string }>;
};
};
registry?: { [key: string]: { tags?: Array<string> } };
steam?: { id: number };
};
};
export default defineTask({
async run(_event) {
const manifest = yaml.load(
await $fetch<string>(
"https://raw.githubusercontent.com/mtkennerly/ludusavi-manifest/refs/heads/master/data/manifest.yaml",
),
) as LudusaviModel;
for (const [name, data] of Object.entries(manifest)) {
if (!data.files && !data.registry) continue;
console.log(name);
const iterableFiles = data.files ? Object.entries(data.files) : undefined;
function findFilesForOperatingSystem(os: string) {
return iterableFiles?.filter((e) =>
e[1].when?.find((v) => v.os === os),
);
}
const connectOrCreate: ConnectOrCreateShorthand[] = [];
const windowsData = {
registry: data.registry,
files: findFilesForOperatingSystem("windows"),
};
if (windowsData.registry || windowsData.files) {
const create: ConnectOrCreateShorthand = {
where: {
ludusaviEntryName_platform: {
ludusaviEntryName: name,
platform: Platform.Windows,
},
},
create: {
platform: Platform.Windows,
files: windowsData.files?.map((e) => e[0]) ?? [],
registry: Object.entries(windowsData.registry ?? {}).map(
(e) => e[0],
),
},
};
connectOrCreate.push(create);
}
const linuxData = {
files: findFilesForOperatingSystem("linux"),
};
if (linuxData.files) {
const create: ConnectOrCreateShorthand = {
where: {
ludusaviEntryName_platform: {
ludusaviEntryName: name,
platform: Platform.Linux,
},
},
create: {
platform: Platform.Linux,
files: linuxData.files?.map((e) => e[0]) ?? [],
registry: [],
},
};
connectOrCreate.push(create);
}
const macData = {
files: findFilesForOperatingSystem("mac"),
};
if (macData.files) {
const create: ConnectOrCreateShorthand = {
where: {
ludusaviEntryName_platform: {
ludusaviEntryName: name,
platform: Platform.macOS,
},
},
create: {
platform: Platform.macOS,
files: macData.files?.map((e) => e[0]) ?? [],
registry: [],
},
};
connectOrCreate.push(create);
}
const steamId = data.steam?.id.toString() ?? null;
await prisma.ludusaviEntry.upsert({
where: {
name,
},
create: {
name,
steamId,
entries: { connectOrCreate },
},
update: {
steamId,
entries: { connectOrCreate },
},
});
}
return { result: true };
},
});