85 lines
2.4 KiB
TypeScript
85 lines
2.4 KiB
TypeScript
import "server-only";
|
|
import { admin, required } from "./supabase";
|
|
export type MapListing = {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
source: "plugin" | "fabric";
|
|
state: string;
|
|
parent_dataset_id: string | null;
|
|
contribution_status: string | null;
|
|
allow_contributions: boolean;
|
|
contribution_server_address: string | null;
|
|
update_state: string | null;
|
|
bounds: { minX: number; minZ: number; maxX: number; maxZ: number };
|
|
panorama_count: number;
|
|
server_id: string;
|
|
owner_id: string;
|
|
cover_path: string | null;
|
|
map_path: string | null;
|
|
rejection_reason: string | null;
|
|
image?: string;
|
|
mapImage?: string;
|
|
credit?: string;
|
|
};
|
|
export async function mediaUrl(path: string | null, expires = 3600) {
|
|
if (!path) return null;
|
|
const { data, error } = await admin()
|
|
.storage.from("minegeo-media")
|
|
.createSignedUrl(path, expires);
|
|
if (error) throw new Error(error.message);
|
|
return data.signedUrl;
|
|
}
|
|
export async function catalog() {
|
|
const client = admin();
|
|
const maps = required(
|
|
await client
|
|
.from("datasets")
|
|
.select("*")
|
|
.eq("state", "published")
|
|
.order("created_at", { ascending: false }),
|
|
) as unknown as MapListing[];
|
|
const servers = required(
|
|
await client.from("catalog_servers").select("*"),
|
|
) as { id: string; name: string; address: string | null }[];
|
|
const owners = maps.length
|
|
? required(
|
|
await client
|
|
.from("profiles")
|
|
.select("id,display_name")
|
|
.in("id", [...new Set(maps.map((m) => m.owner_id))]),
|
|
)
|
|
: [];
|
|
return Promise.all(
|
|
maps.map(async (m) => ({
|
|
...m,
|
|
credit:
|
|
owners.find((p) => p.id === m.owner_id)?.display_name ?? "Explorer",
|
|
image: (await mediaUrl(m.map_path || m.cover_path)) ?? undefined,
|
|
mapImage: (await mediaUrl(m.map_path)) ?? undefined,
|
|
server: servers.find((s) => s.id === m.server_id),
|
|
})),
|
|
);
|
|
}
|
|
export async function getMap(id: string) {
|
|
const map = required(
|
|
await admin()
|
|
.from("datasets")
|
|
.select("*")
|
|
.eq("id", id)
|
|
.eq("state", "published")
|
|
.single(),
|
|
) as MapListing;
|
|
const owner = await admin()
|
|
.from("profiles")
|
|
.select("display_name")
|
|
.eq("id", map.owner_id)
|
|
.maybeSingle();
|
|
return {
|
|
...map,
|
|
credit: owner.data?.display_name ?? "Explorer",
|
|
image: await mediaUrl(map.cover_path),
|
|
mapImage: await mediaUrl(map.map_path),
|
|
};
|
|
}
|