test page
This commit is contained in:
parent
c83f0a1c34
commit
5d3f64f558
681
backend/Cargo.lock
generated
681
backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
prost = "0.14.1"
|
||||
prost-types = "0.14.1"
|
||||
rocket = "0.5.1"
|
||||
rocket = { git = "https://github.com/rwf2/Rocket", rev = "504efef179622df82ba1dbd37f2e0d9ed2b7c9e4" }
|
||||
bytes = "1"
|
||||
rocket_prost_responder_derive = { path = "rocket_prost_responder_derive" }
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::process::Command;
|
||||
|
||||
extern crate prost_build;
|
||||
|
||||
fn main() -> Result<(), std::io::Error> {
|
||||
@ -11,5 +13,14 @@ fn main() -> Result<(), std::io::Error> {
|
||||
);
|
||||
|
||||
cfg.compile_protos(&["../protobuf/items.proto"], &["../protobuf"])?;
|
||||
|
||||
Command::new("pnpm")
|
||||
.arg("run")
|
||||
.arg("build")
|
||||
.current_dir("../frontend")
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
use rocket::{
|
||||
Request,
|
||||
fs::{
|
||||
FileServer,
|
||||
rewrite::{File, Rewrite},
|
||||
},
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
@ -11,8 +19,22 @@ fn get_user(user_list: &rocket::State<Vec<items::Person>>, name: String) -> Opti
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn index(user_list: &rocket::State<Vec<items::Person>>) -> String {
|
||||
format!("Hello, user amount: {}", user_list.len())
|
||||
fn get_users(user_list: &rocket::State<Vec<items::Person>>) -> items::PersonList {
|
||||
items::PersonList {
|
||||
person: user_list
|
||||
.inner()
|
||||
.to_vec()
|
||||
.iter_mut()
|
||||
.map(|x| {
|
||||
x.opinion.clear();
|
||||
x.clone()
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn redir_missing<'r>(p: Option<Rewrite<'r>>, _req: &Request<'_>) -> Option<Rewrite<'r>> {
|
||||
Some(p.unwrap_or_else(|| Rewrite::File(File::checked("../frontend/dist/index.html"))))
|
||||
}
|
||||
|
||||
#[launch]
|
||||
@ -36,5 +58,9 @@ fn rocket() -> _ {
|
||||
|
||||
rocket::build()
|
||||
.manage(user_list)
|
||||
.mount("/", routes![index, get_user])
|
||||
.mount("/api", routes![get_users, get_user])
|
||||
.mount(
|
||||
"/",
|
||||
FileServer::new("../frontend/dist").rewrite(redir_missing),
|
||||
)
|
||||
}
|
||||
|
||||
443
frontend/items.ts
Normal file
443
frontend/items.ts
Normal file
@ -0,0 +1,443 @@
|
||||
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-ts_proto v2.8.3
|
||||
// protoc v6.33.1
|
||||
// source: items.proto
|
||||
|
||||
/* eslint-disable */
|
||||
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
||||
|
||||
export const protobufPackage = "items";
|
||||
|
||||
export enum Source {
|
||||
STEAM = 0,
|
||||
ROBLOX = 1,
|
||||
UNRECOGNIZED = -1,
|
||||
}
|
||||
|
||||
export function sourceFromJSON(object: any): Source {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "STEAM":
|
||||
return Source.STEAM;
|
||||
case 1:
|
||||
case "ROBLOX":
|
||||
return Source.ROBLOX;
|
||||
case -1:
|
||||
case "UNRECOGNIZED":
|
||||
default:
|
||||
return Source.UNRECOGNIZED;
|
||||
}
|
||||
}
|
||||
|
||||
export function sourceToJSON(object: Source): string {
|
||||
switch (object) {
|
||||
case Source.STEAM:
|
||||
return "STEAM";
|
||||
case Source.ROBLOX:
|
||||
return "ROBLOX";
|
||||
case Source.UNRECOGNIZED:
|
||||
default:
|
||||
return "UNRECOGNIZED";
|
||||
}
|
||||
}
|
||||
|
||||
export interface Person {
|
||||
name: string;
|
||||
opinion: Opinion[];
|
||||
}
|
||||
|
||||
export interface Opinion {
|
||||
game: Game | undefined;
|
||||
wouldPlay: boolean;
|
||||
}
|
||||
|
||||
export interface Game {
|
||||
title: string;
|
||||
source: Source;
|
||||
multiplayer: boolean;
|
||||
minPlayers: number;
|
||||
maxPlayers: number;
|
||||
price: number;
|
||||
}
|
||||
|
||||
export interface PersonList {
|
||||
person: Person[];
|
||||
}
|
||||
|
||||
function createBasePerson(): Person {
|
||||
return { name: "", opinion: [] };
|
||||
}
|
||||
|
||||
export const Person: MessageFns<Person> = {
|
||||
encode(message: Person, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.name !== "") {
|
||||
writer.uint32(10).string(message.name);
|
||||
}
|
||||
for (const v of message.opinion) {
|
||||
Opinion.encode(v!, writer.uint32(18).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): Person {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
const end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBasePerson();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.opinion.push(Opinion.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): Person {
|
||||
return {
|
||||
name: isSet(object.name) ? globalThis.String(object.name) : "",
|
||||
opinion: globalThis.Array.isArray(object?.opinion) ? object.opinion.map((e: any) => Opinion.fromJSON(e)) : [],
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: Person): unknown {
|
||||
const obj: any = {};
|
||||
if (message.name !== "") {
|
||||
obj.name = message.name;
|
||||
}
|
||||
if (message.opinion?.length) {
|
||||
obj.opinion = message.opinion.map((e) => Opinion.toJSON(e));
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<Person>, I>>(base?: I): Person {
|
||||
return Person.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<Person>, I>>(object: I): Person {
|
||||
const message = createBasePerson();
|
||||
message.name = object.name ?? "";
|
||||
message.opinion = object.opinion?.map((e) => Opinion.fromPartial(e)) || [];
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseOpinion(): Opinion {
|
||||
return { game: undefined, wouldPlay: false };
|
||||
}
|
||||
|
||||
export const Opinion: MessageFns<Opinion> = {
|
||||
encode(message: Opinion, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.game !== undefined) {
|
||||
Game.encode(message.game, writer.uint32(10).fork()).join();
|
||||
}
|
||||
if (message.wouldPlay !== false) {
|
||||
writer.uint32(16).bool(message.wouldPlay);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): Opinion {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
const end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseOpinion();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.game = Game.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 16) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.wouldPlay = reader.bool();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): Opinion {
|
||||
return {
|
||||
game: isSet(object.game) ? Game.fromJSON(object.game) : undefined,
|
||||
wouldPlay: isSet(object.wouldPlay) ? globalThis.Boolean(object.wouldPlay) : false,
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: Opinion): unknown {
|
||||
const obj: any = {};
|
||||
if (message.game !== undefined) {
|
||||
obj.game = Game.toJSON(message.game);
|
||||
}
|
||||
if (message.wouldPlay !== false) {
|
||||
obj.wouldPlay = message.wouldPlay;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<Opinion>, I>>(base?: I): Opinion {
|
||||
return Opinion.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<Opinion>, I>>(object: I): Opinion {
|
||||
const message = createBaseOpinion();
|
||||
message.game = (object.game !== undefined && object.game !== null) ? Game.fromPartial(object.game) : undefined;
|
||||
message.wouldPlay = object.wouldPlay ?? false;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseGame(): Game {
|
||||
return { title: "", source: 0, multiplayer: false, minPlayers: 0, maxPlayers: 0, price: 0 };
|
||||
}
|
||||
|
||||
export const Game: MessageFns<Game> = {
|
||||
encode(message: Game, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.title !== "") {
|
||||
writer.uint32(10).string(message.title);
|
||||
}
|
||||
if (message.source !== 0) {
|
||||
writer.uint32(16).int32(message.source);
|
||||
}
|
||||
if (message.multiplayer !== false) {
|
||||
writer.uint32(24).bool(message.multiplayer);
|
||||
}
|
||||
if (message.minPlayers !== 0) {
|
||||
writer.uint32(32).uint32(message.minPlayers);
|
||||
}
|
||||
if (message.maxPlayers !== 0) {
|
||||
writer.uint32(40).uint32(message.maxPlayers);
|
||||
}
|
||||
if (message.price !== 0) {
|
||||
writer.uint32(48).uint32(message.price);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): Game {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
const end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseGame();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.title = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 16) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.source = reader.int32() as any;
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 24) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.multiplayer = reader.bool();
|
||||
continue;
|
||||
}
|
||||
case 4: {
|
||||
if (tag !== 32) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.minPlayers = reader.uint32();
|
||||
continue;
|
||||
}
|
||||
case 5: {
|
||||
if (tag !== 40) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.maxPlayers = reader.uint32();
|
||||
continue;
|
||||
}
|
||||
case 6: {
|
||||
if (tag !== 48) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.price = reader.uint32();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): Game {
|
||||
return {
|
||||
title: isSet(object.title) ? globalThis.String(object.title) : "",
|
||||
source: isSet(object.source) ? sourceFromJSON(object.source) : 0,
|
||||
multiplayer: isSet(object.multiplayer) ? globalThis.Boolean(object.multiplayer) : false,
|
||||
minPlayers: isSet(object.minPlayers) ? globalThis.Number(object.minPlayers) : 0,
|
||||
maxPlayers: isSet(object.maxPlayers) ? globalThis.Number(object.maxPlayers) : 0,
|
||||
price: isSet(object.price) ? globalThis.Number(object.price) : 0,
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: Game): unknown {
|
||||
const obj: any = {};
|
||||
if (message.title !== "") {
|
||||
obj.title = message.title;
|
||||
}
|
||||
if (message.source !== 0) {
|
||||
obj.source = sourceToJSON(message.source);
|
||||
}
|
||||
if (message.multiplayer !== false) {
|
||||
obj.multiplayer = message.multiplayer;
|
||||
}
|
||||
if (message.minPlayers !== 0) {
|
||||
obj.minPlayers = Math.round(message.minPlayers);
|
||||
}
|
||||
if (message.maxPlayers !== 0) {
|
||||
obj.maxPlayers = Math.round(message.maxPlayers);
|
||||
}
|
||||
if (message.price !== 0) {
|
||||
obj.price = Math.round(message.price);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<Game>, I>>(base?: I): Game {
|
||||
return Game.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<Game>, I>>(object: I): Game {
|
||||
const message = createBaseGame();
|
||||
message.title = object.title ?? "";
|
||||
message.source = object.source ?? 0;
|
||||
message.multiplayer = object.multiplayer ?? false;
|
||||
message.minPlayers = object.minPlayers ?? 0;
|
||||
message.maxPlayers = object.maxPlayers ?? 0;
|
||||
message.price = object.price ?? 0;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBasePersonList(): PersonList {
|
||||
return { person: [] };
|
||||
}
|
||||
|
||||
export const PersonList: MessageFns<PersonList> = {
|
||||
encode(message: PersonList, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
for (const v of message.person) {
|
||||
Person.encode(v!, writer.uint32(10).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): PersonList {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
const end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBasePersonList();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.person.push(Person.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): PersonList {
|
||||
return {
|
||||
person: globalThis.Array.isArray(object?.person) ? object.person.map((e: any) => Person.fromJSON(e)) : [],
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: PersonList): unknown {
|
||||
const obj: any = {};
|
||||
if (message.person?.length) {
|
||||
obj.person = message.person.map((e) => Person.toJSON(e));
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<PersonList>, I>>(base?: I): PersonList {
|
||||
return PersonList.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<PersonList>, I>>(object: I): PersonList {
|
||||
const message = createBasePersonList();
|
||||
message.person = object.person?.map((e) => Person.fromPartial(e)) || [];
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
||||
|
||||
export type DeepPartial<T> = T extends Builtin ? T
|
||||
: T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>>
|
||||
: T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Partial<T>;
|
||||
|
||||
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||
export type Exact<P, I extends P> = P extends Builtin ? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
|
||||
|
||||
function isSet(value: any): boolean {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
export interface MessageFns<T> {
|
||||
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
||||
fromJSON(object: any): T;
|
||||
toJSON(message: T): unknown;
|
||||
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
|
||||
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
|
||||
}
|
||||
@ -7,9 +7,11 @@
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"gen:proto": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. -I ../protobuf items.proto"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bufbuild/protobuf": "^2.10.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0"
|
||||
},
|
||||
@ -23,6 +25,7 @@
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"globals": "^16.5.0",
|
||||
"ts-proto": "^2.8.3",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.4",
|
||||
"vite": "npm:rolldown-vite@7.2.5"
|
||||
|
||||
56
frontend/pnpm-lock.yaml
generated
56
frontend/pnpm-lock.yaml
generated
@ -11,6 +11,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@bufbuild/protobuf':
|
||||
specifier: ^2.10.1
|
||||
version: 2.10.1
|
||||
react:
|
||||
specifier: ^19.2.0
|
||||
version: 19.2.0
|
||||
@ -45,6 +48,9 @@ importers:
|
||||
globals:
|
||||
specifier: ^16.5.0
|
||||
version: 16.5.0
|
||||
ts-proto:
|
||||
specifier: ^2.8.3
|
||||
version: 2.8.3
|
||||
typescript:
|
||||
specifier: ~5.9.3
|
||||
version: 5.9.3
|
||||
@ -140,6 +146,9 @@ packages:
|
||||
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@bufbuild/protobuf@2.10.1':
|
||||
resolution: {integrity: sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg==}
|
||||
|
||||
'@emnapi/core@1.7.1':
|
||||
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
|
||||
|
||||
@ -460,6 +469,10 @@ packages:
|
||||
caniuse-lite@1.0.30001757:
|
||||
resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==}
|
||||
|
||||
case-anything@2.1.13:
|
||||
resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==}
|
||||
engines: {node: '>=12.13'}
|
||||
|
||||
chalk@4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -496,10 +509,18 @@ packages:
|
||||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
detect-libc@1.0.3:
|
||||
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
|
||||
detect-libc@2.1.2:
|
||||
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
dprint-node@1.0.8:
|
||||
resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==}
|
||||
|
||||
electron-to-chromium@1.5.262:
|
||||
resolution: {integrity: sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==}
|
||||
|
||||
@ -939,6 +960,16 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4'
|
||||
|
||||
ts-poet@6.12.0:
|
||||
resolution: {integrity: sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==}
|
||||
|
||||
ts-proto-descriptors@2.0.0:
|
||||
resolution: {integrity: sha512-wHcTH3xIv11jxgkX5OyCSFfw27agpInAd6yh89hKG6zqIXnjW9SYqSER2CVQxdPj4czeOhGagNvZBEbJPy7qkw==}
|
||||
|
||||
ts-proto@2.8.3:
|
||||
resolution: {integrity: sha512-TdXInqG+61pj/TvORqITWjvjTTsL1EZxwX49iEj89+xFAcqPT8tjChpAGQXzfcF4MJwvNiuoCEbBOKqVf3ds3g==}
|
||||
hasBin: true
|
||||
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
@ -1109,6 +1140,8 @@ snapshots:
|
||||
'@babel/helper-string-parser': 7.27.1
|
||||
'@babel/helper-validator-identifier': 7.28.5
|
||||
|
||||
'@bufbuild/protobuf@2.10.1': {}
|
||||
|
||||
'@emnapi/core@1.7.1':
|
||||
dependencies:
|
||||
'@emnapi/wasi-threads': 1.1.0
|
||||
@ -1450,6 +1483,8 @@ snapshots:
|
||||
|
||||
caniuse-lite@1.0.30001757: {}
|
||||
|
||||
case-anything@2.1.13: {}
|
||||
|
||||
chalk@4.1.2:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
@ -1479,8 +1514,14 @@ snapshots:
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
detect-libc@1.0.3: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
|
||||
dprint-node@1.0.8:
|
||||
dependencies:
|
||||
detect-libc: 1.0.3
|
||||
|
||||
electron-to-chromium@1.5.262: {}
|
||||
|
||||
escalade@3.2.0: {}
|
||||
@ -1848,6 +1889,21 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 5.9.3
|
||||
|
||||
ts-poet@6.12.0:
|
||||
dependencies:
|
||||
dprint-node: 1.0.8
|
||||
|
||||
ts-proto-descriptors@2.0.0:
|
||||
dependencies:
|
||||
'@bufbuild/protobuf': 2.10.1
|
||||
|
||||
ts-proto@2.8.3:
|
||||
dependencies:
|
||||
'@bufbuild/protobuf': 2.10.1
|
||||
case-anything: 2.1.13
|
||||
ts-poet: 6.12.0
|
||||
ts-proto-descriptors: 2.0.0
|
||||
|
||||
tslib@2.8.1:
|
||||
optional: true
|
||||
|
||||
|
||||
@ -1,33 +1,37 @@
|
||||
import { useState } from 'react'
|
||||
import reactLogo from './assets/react.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Person, PersonList } from '../items'
|
||||
import './App.css'
|
||||
|
||||
function App() {
|
||||
const [count, setCount] = useState(0)
|
||||
const [people, setPeople] = useState<Person[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api')
|
||||
.then((res) => res.arrayBuffer())
|
||||
.then((buffer) => {
|
||||
const list = PersonList.decode(new Uint8Array(buffer))
|
||||
setPeople(list.person)
|
||||
})
|
||||
.catch((err) => console.error('Failed to fetch people:', err))
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<a href="https://vite.dev" target="_blank">
|
||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://react.dev" target="_blank">
|
||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + React</h1>
|
||||
<div className="card">
|
||||
<button onClick={() => setCount((count) => count + 1)}>
|
||||
count is {count}
|
||||
</button>
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to test HMR
|
||||
</p>
|
||||
<h2>People List</h2>
|
||||
{people.map((person, index) => (
|
||||
<div key={index}>
|
||||
<h3>{person.name}</h3>
|
||||
<ul>
|
||||
{person.opinion.map((op, i) => (
|
||||
<li key={i}>
|
||||
{op.game?.title} - {op.wouldPlay ? 'Would Play' : 'Would Not Play'}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="read-the-docs">
|
||||
Click on the Vite and React logos to learn more
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -3,11 +3,16 @@
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"lib": [
|
||||
"ES2022",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"types": ["vite/client"],
|
||||
"types": [
|
||||
"vite/client"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
@ -15,14 +20,15 @@
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"erasableSyntaxOnly": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
||||
@ -3,25 +3,27 @@ syntax = "proto3";
|
||||
package items;
|
||||
|
||||
message Person {
|
||||
string name = 1;
|
||||
repeated Opinion opinion = 2;
|
||||
string name = 1;
|
||||
repeated Opinion opinion = 2;
|
||||
}
|
||||
|
||||
message Opinion {
|
||||
Game game = 1;
|
||||
bool would_play = 2;
|
||||
Game game = 1;
|
||||
bool would_play = 2;
|
||||
}
|
||||
|
||||
message Game {
|
||||
string title = 1;
|
||||
Source source = 2;
|
||||
bool multiplayer = 3;
|
||||
uint32 min_players = 4;
|
||||
uint32 max_players = 5;
|
||||
uint32 price = 6;
|
||||
string title = 1;
|
||||
Source source = 2;
|
||||
bool multiplayer = 3;
|
||||
uint32 min_players = 4;
|
||||
uint32 max_players = 5;
|
||||
uint32 price = 6;
|
||||
}
|
||||
|
||||
enum Source {
|
||||
STEAM = 0;
|
||||
ROBLOX = 1;
|
||||
STEAM = 0;
|
||||
ROBLOX = 1;
|
||||
}
|
||||
|
||||
message PersonList { repeated Person person = 1; }
|
||||
Loading…
x
Reference in New Issue
Block a user