initial work on metadata system

This commit is contained in:
DecDuck
2024-09-29 11:08:49 +10:00
parent ff581f115b
commit d0a92b7932
5 changed files with 278 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
import { _FetchDeveloperMetadataParams, _FetchGameMetadataParams, _FetchPublisherMetadataParams, DeveloperMetadata, GameMetadata, GameMetadataSearchResult, InternalGameMetadataResult, PublisherMetadata } from "./types";
export abstract class MetadataProvider {
abstract id(): string;
abstract name(): string;
abstract search(query: string): Promise<GameMetadataSearchResult[]>;
abstract fetchGame(params: _FetchGameMetadataParams): Promise<GameMetadata>;
abstract fetchPublisher(params: _FetchPublisherMetadataParams): Promise<PublisherMetadata>;
abstract fetchDeveloper(params: _FetchDeveloperMetadataParams): Promise<DeveloperMetadata>;
}
class MetadataHandler {
// Ordered by priority
private providers: Map<string, MetadataProvider> = new Map();
private createObject: (url: string) => Promise<string>;
constructor() {
this.createObject = async () => "";
}
async search(query: string) {
const promises: Promise<InternalGameMetadataResult[]>[] = [];
for (const provider of this.providers.values()) {
const queryTransformationPromise = new Promise<InternalGameMetadataResult[]>(async (resolve, reject) => {
const results = await provider.search(query);
const mappedResults: InternalGameMetadataResult[] = results.map((result) => Object.assign(
{},
result,
{
sourceId: provider.id(),
sourceName: provider.name()
}
));
resolve(mappedResults);
});
promises.push(queryTransformationPromise);
}
const results = await Promise.allSettled(promises);
const successfulResults = results.filter((result) => result.status === 'fulfilled').map((result) => result.value).flat();
return successfulResults;
}
async fetchGame(game: InternalGameMetadataResult) {
}
async fetchDeveloper(query: string) {
}
}
export default new MetadataHandler();
+64
View File
@@ -0,0 +1,64 @@
import { Developer, Publisher } from "@prisma/client";
export interface GameMetadataSearchResult {
id: string;
name: string;
icon: string;
description: string;
year: number;
}
export interface GameMetadataSource {
sourceId: string;
sourceName: string;
}
export type InternalGameMetadataResult = GameMetadataSearchResult & GameMetadataSource;
export type RemoteObject = string;
export interface GameMetadata {
name: string;
shortDescription: string;
description: string;
// These are created using utility functions passed to the metadata loader
// (that then call back into the metadata provider chain)
publishers: Publisher[]
developers: Developer[]
reviewCount: number;
reviewRating: number;
// Created with another utility function
icon: RemoteObject,
banner: RemoteObject,
art: RemoteObject[],
screenshots: RemoteObject[],
}
export interface PublisherMetadata {
name: string;
shortDescription: string;
description: string;
logo: RemoteObject;
banner: RemoteObject;
}
export type DeveloperMetadata = PublisherMetadata;
export interface _FetchGameMetadataParams {
id: string,
publisher: (query: string) => Promise<Publisher>
developer: (query: string) => Promise<Developer>
createObject: (url: string) => Promise<RemoteObject>
}
export interface _FetchPublisherMetadataParams {
query: string;
createObject: (url: string) => Promise<RemoteObject>;
}
export type _FetchDeveloperMetadataParams = _FetchPublisherMetadataParams;