Add Backend Validation
Dieser Commit ist enthalten in:
Ursprung
b14ef2981e
Commit
4a501ea870
11
package.json
11
package.json
@ -14,6 +14,10 @@
|
||||
"@tsconfig/svelte": "^4.0.1",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"flowbite-svelte-icons": "^0.2.5",
|
||||
"flowbite": "^1.7.0",
|
||||
"flowbite-svelte": "^0.39.2",
|
||||
"svelte-awesome": "^3.2.0",
|
||||
"tailwind-merge": "^1.13.2",
|
||||
"postcss": "^8.4.24",
|
||||
"sass": "^1.62.0",
|
||||
"svelte": "^4.0.1",
|
||||
@ -25,14 +29,9 @@
|
||||
"vite": "^4.3.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"color": "^4.2.3",
|
||||
"flowbite": "^1.7.0",
|
||||
"flowbite-svelte": "^0.39.2",
|
||||
"install": "^0.13.0",
|
||||
"moment": "^2.29.4",
|
||||
"svelte-awesome": "^3.2.0",
|
||||
"svelte-spa-router": "^3.3.0",
|
||||
"tailwind-merge": "^1.13.2"
|
||||
"zod": "^3.21.4"
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ dependencies:
|
||||
tailwind-merge:
|
||||
specifier: ^1.13.2
|
||||
version: 1.13.2
|
||||
zod:
|
||||
specifier: ^3.21.4
|
||||
version: 3.21.4
|
||||
|
||||
devDependencies:
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
@ -1459,6 +1462,10 @@ packages:
|
||||
engines: {node: '>= 14'}
|
||||
dev: true
|
||||
|
||||
/zod@3.21.4:
|
||||
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
||||
dev: false
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
@ -1,6 +1,8 @@
|
||||
import type {ExtendedEvent, ShortEvent, SWEvent} from "../types/event.js";
|
||||
import {fetchWithToken} from "./repo.js";
|
||||
import type {Moment} from "moment";
|
||||
import {ExtendedEventSchema, ShortEventSchema, SWEventSchema} from "../types/event.js";
|
||||
import {z} from "zod";
|
||||
|
||||
export interface CreateEvent {
|
||||
name: string
|
||||
@ -26,7 +28,7 @@ export class EventRepo {
|
||||
const res = await fetchWithToken(this.token, "/events");
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as ShortEvent[];
|
||||
return z.array(ShortEventSchema).parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch events: " + res.statusText);
|
||||
}
|
||||
@ -36,7 +38,7 @@ export class EventRepo {
|
||||
const res = await fetchWithToken(this.token, `/events/${id}`);
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as ExtendedEvent;
|
||||
return ExtendedEventSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch event: " + res.statusText);
|
||||
}
|
||||
@ -53,7 +55,7 @@ export class EventRepo {
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as SWEvent;
|
||||
return SWEventSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not create event: " + res.statusText);
|
||||
}
|
||||
@ -78,7 +80,7 @@ export class EventRepo {
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as SWEvent;
|
||||
return SWEventSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not update event: " + res.statusText);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import type {EventFight} from "../types/event.js";
|
||||
import {fetchWithToken} from "./repo.js";
|
||||
import type {Moment} from "moment";
|
||||
import {z} from "zod";
|
||||
import {EventFightSchema} from "../types/event.js";
|
||||
|
||||
export interface CreateFight {
|
||||
spielmodus: string
|
||||
@ -29,7 +31,7 @@ export class FightRepo {
|
||||
const res = await fetchWithToken(this.token, `/events/${eventId}/fights`);
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as EventFight[];
|
||||
return z.array(EventFightSchema).parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch fights: " + res.statusText);
|
||||
}
|
||||
@ -51,7 +53,7 @@ export class FightRepo {
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as EventFight;
|
||||
return EventFightSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not create fight: " + res.statusText);
|
||||
}
|
||||
@ -72,7 +74,7 @@ export class FightRepo {
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
return await res.json() as EventFight;
|
||||
return EventFightSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not update fight: " + res.statusText);
|
||||
}
|
||||
|
@ -3,20 +3,23 @@ import {cached, cachedFamily} from "./cached.js";
|
||||
import type {Team} from "../types/team.js";
|
||||
import {get, writable} from "svelte/store";
|
||||
import {tokenStore} from "../repo/repo.js";
|
||||
import {PlayerSchema} from "../types/data.js";
|
||||
import {z} from "zod";
|
||||
import {TeamSchema} from "../types/team.js";
|
||||
|
||||
export const schemTypes = cached<SchematicType[]>([], () => {
|
||||
return fetch("https://steamwar.de/eventplanner-api/data/schematicTypes", {headers: {"X-SW-Auth": get(tokenStore)}})
|
||||
.then(res => res.json())
|
||||
})
|
||||
|
||||
export const players = cached<Player[]>([], () => {
|
||||
return fetch("https://steamwar.de/eventplanner-api/data/users", {headers: {"X-SW-Auth": get(tokenStore)}})
|
||||
.then(res => res.json())
|
||||
export const players = cached<Player[]>([], async () => {
|
||||
const res = await fetch("https://steamwar.de/eventplanner-api/data/users", {headers: {"X-SW-Auth": get(tokenStore)}});
|
||||
return z.array(PlayerSchema).parse(await res.json());
|
||||
})
|
||||
|
||||
export const gamemodes = cached<string[]>([], () => {
|
||||
return fetch("https://steamwar.de/eventplanner-api/data/gamemodes", {headers: {"X-SW-Auth": get(tokenStore)}})
|
||||
.then(res => res.json())
|
||||
export const gamemodes = cached<string[]>([], async () => {
|
||||
const res = await fetch("https://steamwar.de/eventplanner-api/data/gamemodes", {headers: {"X-SW-Auth": get(tokenStore)}});
|
||||
return z.array(z.string()).parse(await res.json());
|
||||
})
|
||||
|
||||
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
||||
@ -30,14 +33,14 @@ export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
||||
}
|
||||
})
|
||||
|
||||
export const groups = cached<string[]>([], () => {
|
||||
return fetch("https://steamwar.de/eventplanner-api/data/groups", {headers: {"X-SW-Auth": get(tokenStore)}})
|
||||
.then(res => res.json())
|
||||
export const groups = cached<string[]>([], async () => {
|
||||
const res = await fetch("https://steamwar.de/eventplanner-api/data/groups", {headers: {"X-SW-Auth": get(tokenStore)}});
|
||||
return z.array(z.string()).parse(await res.json());
|
||||
})
|
||||
|
||||
export const teams = cached<Team[]>([], () => {
|
||||
return fetch("https://steamwar.de/eventplanner-api/team", {headers: {"X-SW-Auth": get(tokenStore)}})
|
||||
.then(res => res.json())
|
||||
export const teams = cached<Team[]>([], async () => {
|
||||
const res = await fetch("https://steamwar.de/eventplanner-api/team", {headers: {"X-SW-Auth": get(tokenStore)}});
|
||||
return z.array(TeamSchema).parse(await res.json());
|
||||
})
|
||||
|
||||
export const isWide = writable(window.innerWidth >= 640);
|
||||
|
@ -1,10 +1,16 @@
|
||||
export interface SchematicType {
|
||||
name: string;
|
||||
db: string;
|
||||
}
|
||||
import {z} from "zod";
|
||||
|
||||
export interface Player {
|
||||
id: number;
|
||||
name: string;
|
||||
uuid: string;
|
||||
}
|
||||
export const SchematicTypeSchema = z.object({
|
||||
name: z.string(),
|
||||
db: z.string(),
|
||||
})
|
||||
|
||||
export type SchematicType = z.infer<typeof SchematicTypeSchema>;
|
||||
|
||||
export const PlayerSchema = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
uuid: z.string().uuid(),
|
||||
})
|
||||
|
||||
export type Player = z.infer<typeof PlayerSchema>;
|
||||
|
@ -1,35 +1,46 @@
|
||||
import type {Team} from "./team.js";
|
||||
import type {Player} from "./data.js";
|
||||
import {z} from "zod";
|
||||
import {TeamSchema} from "./team.js";
|
||||
import {PlayerSchema} from "./data.js";
|
||||
|
||||
export interface ShortEvent {
|
||||
id: number;
|
||||
name: string;
|
||||
start: number;
|
||||
end: number;
|
||||
}
|
||||
export const ShortEventSchema = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
start: z.number(),
|
||||
end: z.number(),
|
||||
})
|
||||
|
||||
export interface SWEvent extends ShortEvent {
|
||||
deadline: number;
|
||||
maxTeamMembers: number;
|
||||
schemType: string | null;
|
||||
publicSchemsOnly: boolean;
|
||||
spectateSystem: boolean;
|
||||
}
|
||||
export type ShortEvent = z.infer<typeof ShortEventSchema>;
|
||||
|
||||
export interface EventFight {
|
||||
id: number;
|
||||
spielmodus: string;
|
||||
map: string;
|
||||
blueTeam: Team;
|
||||
redTeam: Team;
|
||||
kampfleiter: Player | null;
|
||||
start: number;
|
||||
ergebnis: number;
|
||||
group: string | null;
|
||||
}
|
||||
export const SWEventSchema = ShortEventSchema.extend({
|
||||
deadline: z.number(),
|
||||
maxTeamMembers: z.number(),
|
||||
schemType: z.string().nullable(),
|
||||
publicSchemsOnly: z.boolean(),
|
||||
spectateSystem: z.boolean(),
|
||||
})
|
||||
|
||||
export interface ExtendedEvent {
|
||||
event: SWEvent;
|
||||
teams: Team[];
|
||||
fights: EventFight[];
|
||||
}
|
||||
export type SWEvent = z.infer<typeof SWEventSchema>;
|
||||
|
||||
export const EventFightSchema = z.object({
|
||||
id: z.number(),
|
||||
spielmodus: z.string(),
|
||||
map: z.string(),
|
||||
blueTeam: TeamSchema,
|
||||
redTeam: TeamSchema,
|
||||
kampfleiter: PlayerSchema.nullable(),
|
||||
start: z.number(),
|
||||
ergebnis: z.number(),
|
||||
group: z.string().nullable(),
|
||||
})
|
||||
|
||||
export type EventFight = z.infer<typeof EventFightSchema>;
|
||||
|
||||
export const ExtendedEventSchema = z.object({
|
||||
event: SWEventSchema,
|
||||
teams: z.array(TeamSchema),
|
||||
fights: z.array(EventFightSchema),
|
||||
})
|
||||
|
||||
export type ExtendedEvent = z.infer<typeof ExtendedEventSchema>;
|
||||
|
@ -1,8 +1,12 @@
|
||||
import Color from "color";
|
||||
import {z} from "zod";
|
||||
|
||||
export const TeamSchema = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
kuerzel: z.string().min(1).max(4),
|
||||
color: z.string().max(1),
|
||||
})
|
||||
|
||||
export type Team = z.infer<typeof TeamSchema>;
|
||||
|
||||
|
||||
export interface Team {
|
||||
id: number;
|
||||
name: string;
|
||||
kuerzel: string;
|
||||
color: string;
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren