Refine workspaces and event publishing; harden uploads and email delivery

This commit is contained in:
2026-09-09 15:44:00 -04:00
parent f5702caaea
commit 574f29a68e
93 changed files with 2885 additions and 535 deletions
+43
View File
@@ -0,0 +1,43 @@
import { z } from "zod";
import { locationSuggestionSchema, type LocationSuggestion } from "@album/contracts";
const photonSchema = z.object({
features: z.array(z.object({
geometry: z.object({ coordinates: z.tuple([z.number(), z.number()]) }),
properties: z.record(z.unknown()),
})),
});
export function parseLocationResults(payload: unknown): LocationSuggestion[] {
const parsed = photonSchema.parse(payload);
const seen = new Set<string>();
return parsed.features.flatMap(({ geometry, properties }) => {
const text = (key: string) => typeof properties[key] === "string" ? properties[key] as string : "";
const street = [text("housenumber"), text("street")].filter(Boolean).join(" ");
const address = [...new Set([
text("name"), street, text("city") || text("district") || text("county"),
text("state"), text("postcode"), text("country"),
].filter(Boolean))].join(", ");
const result = locationSuggestionSchema.safeParse({
address, longitude: geometry.coordinates[0], latitude: geometry.coordinates[1],
});
const key = `${address}:${geometry.coordinates.join(",")}`;
if (!address || !result.success || seen.has(key)) return [];
seen.add(key);
return [result.data];
});
}
export async function searchLocations(query: string) {
const url = new URL("https://photon.komoot.io/api/");
url.searchParams.set("q", query);
url.searchParams.set("limit", "6");
url.searchParams.set("lang", "en");
const response = await fetch(url, {
headers: { Accept: "application/json", "User-Agent": "Manyangles event location search" },
next: { revalidate: 86_400 },
signal: AbortSignal.timeout(8000),
});
if (!response.ok) throw new Error("Location search unavailable");
return parseLocationResults(await response.json());
}