adds zod API validation

This commit is contained in:
Christian Beutel
2024-12-27 01:56:35 +01:00
parent 1f81779a64
commit 75c94a3ce4
80 changed files with 847 additions and 559 deletions

View File

@@ -5,7 +5,7 @@ let activities: Activity[] = [];
export async function activities_index(author: string, page: number = 1, perPage: number = 10, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f('/api/v1/activity?' + new URLSearchParams({
"per-page": perPage.toString(),
"perPage": perPage.toString(),
page: page.toString(),
filter: `author="${author}"`
}), {

View File

@@ -1,7 +1,7 @@
import { pb } from "$lib/pocketbase";
import type { Category } from "$lib/models/category";
import { writable, type Writable } from "svelte/store";
import { ClientResponseError } from "pocketbase";
import { ClientResponseError, type ListResult } from "pocketbase";
export const categories: Writable<Category[]> = writable([])
@@ -14,9 +14,9 @@ export async function categories_index(f: (url: RequestInfo | URL, config?: Requ
throw new ClientResponseError(await r.json())
}
const response = await r.json();
const response: ListResult<Category> = await r.json();
categories.set(response);
categories.set(response.items);
return response as Category[];
return response.items as Category[];
}

View File

@@ -1,7 +1,7 @@
import { Comment } from "$lib/models/comment";
import type { Trail } from "$lib/models/trail";
import { pb } from "$lib/pocketbase";
import { ClientResponseError } from "pocketbase";
import { ClientResponseError, type ListResult } from "pocketbase";
import { writable, type Writable } from "svelte/store";
export const comments: Writable<Comment[]> = writable([])
@@ -9,6 +9,7 @@ export const comments: Writable<Comment[]> = writable([])
export async function comments_index(trail: Trail) {
let r = await fetch('/api/v1/comment?' + new URLSearchParams({
filter: `trail="${trail.id}"`,
sort: "-created"
}), {
method: 'GET',
})
@@ -17,11 +18,11 @@ export async function comments_index(trail: Trail) {
throw new ClientResponseError(await r.json())
}
const fetchedComments: Comment[] = await r.json();
const fetchedComments: ListResult<Comment> = await r.json();
comments.set(fetchedComments);
comments.set(fetchedComments.items);
return fetchedComments;
return fetchedComments.items;
}
export async function comments_create(comment: Comment) {

View File

@@ -7,7 +7,8 @@ export async function follows_index(data: { follower?: string, followee?: string
const r = await f('/api/v1/follow?' + new URLSearchParams({
filter: data.follower ? `follower='${data.follower}'` : data.followee ? `followee='${data.followee}'` : '',
page: page.toString(),
"per-page": perPage.toString()
perPage: perPage.toString(),
requestKey: "page"
}), {
method: 'GET',
})

View File

@@ -1,5 +1,5 @@
import type { ListShare } from "$lib/models/list_share";
import { ClientResponseError } from "pocketbase";
import { ClientResponseError, type ListResult } from "pocketbase";
import { writable, type Writable } from "svelte/store";
export const shares: Writable<ListShare[]> = writable([])
@@ -16,9 +16,9 @@ export async function list_share_index(list: string, f: (url: RequestInfo | URL,
throw new ClientResponseError(await r.json())
}
const response: ListShare[] = await r.json();
const response: ListResult<ListShare> = await r.json();
shares.set(response);
shares.set(response.items);
return response;

View File

@@ -2,7 +2,7 @@ import { List, type ListFilter } from "$lib/models/list";
import type { Trail } from "$lib/models/trail";
import { pb } from "$lib/pocketbase";
import { ClientResponseError, type ListResult } from "pocketbase";
import { get, writable, type Writable } from "svelte/store";
import { writable, type Writable } from "svelte/store";
import { fetchGPX } from "./trail_store";
let lists: List[] = []
@@ -14,9 +14,10 @@ export async function lists_index(filter?: ListFilter, page: number = 1, perPage
const r = await f('/api/v1/list?' + new URLSearchParams({
sort: `${filter?.sortOrder ?? "-"}${filter?.sort ?? "name"}`,
"per-page": perPage.toString(),
perPage: perPage.toString(),
page: page.toString(),
filter: filterText
filter: filterText,
expand: "trails,trails.waypoints,trails.category,list_share_via_list"
}), {
method: 'GET',
})
@@ -36,7 +37,9 @@ export async function lists_index(filter?: ListFilter, page: number = 1, perPage
}
export async function lists_show(id: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f(`/api/v1/list/${id}`, {
const r = await f(`/api/v1/list/${id}?` + new URLSearchParams({
expand: "trails,trails.waypoints,trails.category,list_share_via_list"
}), {
method: 'GET',
})
const response = await r.json()
@@ -132,6 +135,10 @@ export async function lists_add_trail(list: List, trail: Trail) {
if (!r.ok) {
throw new ClientResponseError(await r.json())
}
const model: List = await r.json();
return model;
}
export async function lists_remove_trail(list: List, trail: Trail) {
@@ -145,6 +152,10 @@ export async function lists_remove_trail(list: List, trail: Trail) {
if (!r.ok) {
throw new ClientResponseError(await r.json())
}
const model: List = await r.json();
return model;
}
export async function lists_delete(list: List) {

View File

@@ -1,6 +1,6 @@
import { SummitLog, type SummitLogFilter } from "$lib/models/summit_log";
import { pb } from "$lib/pocketbase";
import { ClientResponseError } from "pocketbase";
import { ClientResponseError, type ListResult } from "pocketbase";
import { writable, type Writable } from "svelte/store";
import { fetchGPX } from "./trail_store";
@@ -14,6 +14,8 @@ export async function summit_logs_index(author: string, filter?: SummitLogFilter
const r = await f('/api/v1/summit-log?' + new URLSearchParams({
filter: filterText,
expand: "trails_via_summit_logs.category",
sort: "+date",
}), {
method: 'GET',
})
@@ -22,9 +24,9 @@ export async function summit_logs_index(author: string, filter?: SummitLogFilter
throw new ClientResponseError(await r.json())
}
const fetchedSummitLogs: SummitLog[] = await r.json();
const fetchedSummitLogs: ListResult<SummitLog> = await r.json();
for (const log of fetchedSummitLogs) {
for (const log of fetchedSummitLogs.items) {
if (!log.gpx) {
continue
}
@@ -36,7 +38,7 @@ export async function summit_logs_index(author: string, filter?: SummitLogFilter
log.expand.gpx_data = gpxData;
}
summitLogs.set(fetchedSummitLogs);
summitLogs.set(fetchedSummitLogs.items);
return fetchedSummitLogs;
}
@@ -82,7 +84,7 @@ export async function summit_logs_create(summitLog: SummitLog, f: (url: RequestI
}
if (r.ok) {
return await r.json();
return model;
} else {
throw new ClientResponseError(await r.json())
}

View File

@@ -1,5 +1,5 @@
import type { TrailShare } from "$lib/models/trail_share";
import { ClientResponseError } from "pocketbase";
import { ClientResponseError, type ListResult } from "pocketbase";
import { writable, type Writable } from "svelte/store";
export const shares: Writable<TrailShare[]> = writable([])
@@ -16,11 +16,11 @@ export async function trail_share_index(data: {trail?: string, user?: string}, f
throw new ClientResponseError(await r.json())
}
const response: TrailShare[] = await r.json();
const response: ListResult<TrailShare> = await r.json();
shares.set(response);
shares.set(response.items);
return response;
return response.items;
}

View File

@@ -179,14 +179,14 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | Bl
throw new ClientResponseError({ status: 401, response: { message: "Forbidden" } });
}
for (const waypoint of trail.expand.waypoints) {
for (const waypoint of trail.expand?.waypoints ?? []) {
const model = await waypoints_create({
...waypoint,
marker: undefined,
}, f);
trail.waypoints.push(model.id!);
}
for (const summitLog of trail.expand.summit_logs) {
for (const summitLog of trail.expand?.summit_logs ?? []) {
const model = await summit_logs_create(summitLog, f);
trail.summit_logs.push(model.id!);
}
@@ -227,7 +227,7 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | Bl
export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: File[], gpx?: File | Blob | null) {
const waypointUpdates = compareObjectArrays<Waypoint>(oldTrail.expand.waypoints ?? [], newTrail.expand.waypoints ?? []);
const waypointUpdates = compareObjectArrays<Waypoint>(oldTrail.expand?.waypoints ?? [], newTrail.expand?.waypoints ?? []);
for (const addedWaypoint of waypointUpdates.added) {
const model = await waypoints_create({
@@ -238,7 +238,7 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
}
for (const updatedWaypoint of waypointUpdates.updated) {
const oldWaypoint = oldTrail.expand.waypoints.find(w => w.id == updatedWaypoint.id);
const oldWaypoint = oldTrail.expand?.waypoints.find(w => w.id == updatedWaypoint.id);
const model = await waypoints_update(oldWaypoint!, {
...updatedWaypoint,
marker: undefined,
@@ -249,7 +249,7 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
const success = await waypoints_delete(deletedWaypoint);
}
const summitLogUpdates = compareObjectArrays<SummitLog>(oldTrail.expand.summit_logs ?? [], newTrail.expand.summit_logs ?? []);
const summitLogUpdates = compareObjectArrays<SummitLog>(oldTrail.expand?.summit_logs ?? [], newTrail.expand?.summit_logs ?? []);
for (const summitLog of summitLogUpdates.added) {
const model = await summit_logs_create(summitLog);
@@ -257,7 +257,7 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
}
for (const updatedSummitLog of summitLogUpdates.updated) {
const oldSummitLog = oldTrail.expand.summit_logs.find(w => w.id == updatedSummitLog.id);
const oldSummitLog = oldTrail.expand?.summit_logs.find(w => w.id == updatedSummitLog.id);
const model = await summit_logs_update(oldSummitLog!, updatedSummitLog);
}
@@ -266,7 +266,9 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
const success = await summit_logs_delete(deletedSummitLog);
}
let r = await fetch('/api/v1/trail/' + newTrail.id, {
let r = await fetch(`/api/v1/trail/${newTrail.id}?` + new URLSearchParams({
expand: "category,waypoints,summit_logs,trail_share_via_trail",
}), {
method: 'POST',
body: JSON.stringify({ ...newTrail, expand: undefined }),
})
@@ -312,12 +314,12 @@ export async function trails_update(oldTrail: Trail, newTrail: Trail, photos?: F
export async function trails_delete(trail: Trail) {
if (trail.expand.waypoints) {
if (trail.expand?.waypoints) {
for (const waypoint of trail.expand.waypoints) {
await waypoints_delete(waypoint);
}
}
if (trail.expand.summit_logs) {
if (trail.expand?.summit_logs) {
for (const summit_log of trail.expand.summit_logs) {
await summit_logs_delete(summit_log);
}

View File

@@ -22,7 +22,7 @@ export async function users_create(user: User) {
export async function users_search(q: string, includeSelf: boolean = true) {
let r = await fetch('/api/v1/user/anonymous?' + new URLSearchParams({
"filter": `username~"${q}"${includeSelf ? '' : '&&id!="${pb.authStore.model?.id}"'}`,
"filter": `username~"${q}"${includeSelf ? '' : `&&id!="${pb.authStore.model?.id}"`}`,
}), {
method: 'GET',
})