Files
blitzkit/packages/website-ue/src/core/api/server.ts
T

103 lines
2.8 KiB
TypeScript
Raw Normal View History

2025-11-28 13:51:17 -06:00
import type { MetadataAccessor } from "@blitzkit/closed";
2025-11-28 14:13:03 -06:00
import { sluggify } from "@blitzkit/core";
import type { RemoteStorageComponent } from "@protos/blitz_static_remote_storage_component";
import { parse } from "yaml";
2025-11-28 13:51:17 -06:00
import type { TanksEntry } from "../../protos/tanks";
import { AbstractAPI } from "./abstract";
2025-11-28 14:13:03 -06:00
interface LocalizationConfig {
namespaces: string[];
}
2025-11-28 13:51:17 -06:00
export class ServerAPI extends AbstractAPI {
constructor(private metadata: MetadataAccessor) {
super();
2025-11-28 14:13:03 -06:00
}
2025-11-28 13:51:17 -06:00
2025-11-28 14:13:03 -06:00
async strings(locale: string) {
const clientConfig = this.metadata.item("ClientConfigsEntity.prod");
const localizationResources = clientConfig.LocalizationResources();
if (!localizationResources.remote_storage) {
throw new Error("Localization resources not found");
}
let remoteStorage: RemoteStorageComponent | undefined = undefined;
for (const candidateId of localizationResources.remote_storage
.remote_urls) {
const item = this.metadata.item(candidateId);
const candidate = item.RemoteStorage();
if (
remoteStorage === undefined ||
candidate.download_speed_weight > remoteStorage.download_speed_weight
) {
remoteStorage = candidate;
}
}
if (remoteStorage === undefined) {
throw new Error("No suitable production remote storage found");
}
const config = await fetch(
`${remoteStorage.url}/${remoteStorage.relative_path}/config.yaml`
)
.then((response) => response.text())
.then((text) => parse(text) as LocalizationConfig);
const strings: Record<string, string> = {};
for (const namespace of config.namespaces) {
Object.assign(
strings,
await fetch(
`${remoteStorage.url}/${remoteStorage.relative_path}/${namespace}/${locale}.yaml`
)
.then((response) => response.text())
.then((text) => {
const strings: Record<string, string> = {};
const parsed = parse(text) as Record<string, string>;
for (const key in parsed) {
strings[key] = parsed[key].replaceAll('\\"', '"');
}
return strings;
})
);
}
return strings;
2025-11-28 13:51:17 -06:00
}
async tanks() {
const group = this.metadata.group("TankEntity");
const tanks: TanksEntry[] = [];
2025-11-28 14:13:03 -06:00
const strings = await this.strings("en");
2025-11-28 13:51:17 -06:00
for (const item of group) {
const tankCatalog = item.TankCatalog();
2025-11-28 14:21:26 -06:00
if (!tankCatalog.name) continue;
const name = strings[tankCatalog.name.value];
if (!name) continue;
2025-11-28 13:51:17 -06:00
2025-11-28 14:13:03 -06:00
const id = item.name;
const slug = sluggify(name);
2025-11-28 13:51:17 -06:00
tanks.push({ id, slug });
}
return { tanks };
}
2025-11-28 14:21:26 -06:00
async tank(id: string) {
const item = this.metadata.item(`TankEntity.${id}`);
const tankCatalog = item.TankCatalog();
return tankCatalog;
}
2025-11-28 13:51:17 -06:00
}