Set up type-safe call and response

This commit is contained in:
Savanni D'Gerinel 2023-05-11 09:39:31 -04:00
parent c87ab6da7f
commit b321c03297
19 changed files with 115 additions and 157 deletions

View File

@ -55,6 +55,7 @@ kifu-pwa:
kifu-pwa/dev:
pushd kifu/ffi/wasm && make && popd
pushd kifu/core-types && make && popd
pushd kifu/kifu-pwa && make dev
kifu-pwa/test-server:

6
kifu/core-types/Makefile Normal file
View File

@ -0,0 +1,6 @@
SOURCES = $(shell find ../kifu-core -name "*.rs")
dist/core.d.ts: $(SOURCES)
mkdir -p dist
typeshare ../kifu-core --lang=typescript --output-file=dist/core.d.ts

View File

@ -0,0 +1,12 @@
{
"name": "core-types",
"version": "0.0.1",
"description": "",
"types": "dist/core.d.ts",
"scripts": {
"build": "make",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Savanni D'Gerinel <savanni@luminescent-dreams.com>",
"license": "GPL-3.0-or-later"
}

View File

@ -172,6 +172,8 @@ name = "kifu-wasm"
version = "0.1.0"
dependencies = [
"kifu-core",
"serde",
"serde-wasm-bindgen",
"wasm-bindgen",
"wasm-bindgen-futures",
]
@ -270,6 +272,17 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-wasm-bindgen"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "serde_derive"
version = "1.0.160"

View File

@ -9,9 +9,11 @@ edition = "2021"
crate-type = ["cdylib"]
[dependencies]
kifu-core = { path = "../../kifu-core" }
wasm-bindgen = "0.2"
wasm-bindgen-futures = "*"
kifu-core = { path = "../../kifu-core" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.5.0"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "*"
[package.metadata.wasm-pack.profile.release]
wasm-opt = false

View File

@ -1,4 +1,6 @@
use wasm_bindgen::prelude::*;
// use serde::{Serialize, Deserialize};
use kifu_core::{CoreRequest, CoreResponse};
#[wasm_bindgen]
extern "C" {
@ -8,8 +10,11 @@ extern "C" {
/*
#[wasm_bindgen]
#[derive(Serialize, Deserialize)]
pub struct CoreRequest(kifu_core::Request);
*/
/*
#[wasm_bindgen]
impl CoreRequest {
#[wasm_bindgen(constructor)]
@ -22,22 +27,26 @@ impl CoreRequest {
/* Somehow uncommenting this code actually causes the module to not load. Maybe a name conflict?
* Don't know.
*/
/*
#[wasm_bindgen]
#[derive(Serialize, Deserialize)]
pub struct CoreResponse(kifu_core::Response);
*/
#[wasm_bindgen]
#[derive(Debug)]
pub struct CoreApp;
pub struct CoreApp(kifu_core::CoreApp);
#[wasm_bindgen]
impl CoreApp {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self
Self(kifu_core::CoreApp::new())
}
#[wasm_bindgen]
pub async fn dispatch(&self, param: &JsValue) {
log(&format!("disptach! {:?}", param));
pub async fn dispatch(&self, param: &JsValue) -> JsValue {
let request: CoreRequest = serde_wasm_bindgen::from_value(param.clone()).unwrap();
serde_wasm_bindgen::to_value(&self.0.dispatch(request).await).unwrap()
}
}

View File

@ -7,7 +7,7 @@ use typeshare::typeshare;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
#[serde(tag = "type", content = "content")]
pub enum Request {
pub enum CoreRequest {
PlayingField,
PlayStoneRequest(PlayStoneRequest),
}
@ -15,14 +15,14 @@ pub enum Request {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
pub struct PlayStoneRequest {
pub column: usize,
pub row: usize,
pub column: u8,
pub row: u8,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[typeshare]
#[serde(tag = "type", content = "content")]
pub enum Response {
pub enum CoreResponse {
PlayingFieldView(PlayingFieldView),
}
@ -38,19 +38,19 @@ impl CoreApp {
Self { state }
}
pub async fn dispatch(&self, request: Request) -> Response {
pub async fn dispatch(&self, request: CoreRequest) -> CoreResponse {
match request {
Request::PlayingField => {
CoreRequest::PlayingField => {
let app_state = self.state.read().unwrap();
let game = app_state.game.as_ref().unwrap();
Response::PlayingFieldView(playing_field(game))
CoreResponse::PlayingFieldView(playing_field(game))
}
Request::PlayStoneRequest(request) => {
CoreRequest::PlayStoneRequest(request) => {
let mut app_state = self.state.write().unwrap();
app_state.place_stone(request);
let game = app_state.game.as_ref().unwrap();
Response::PlayingFieldView(playing_field(game))
CoreResponse::PlayingFieldView(playing_field(game))
}
}
}

View File

@ -73,8 +73,8 @@ impl Board {
#[derive(Clone, Copy, Debug, PartialEq, Hash, Eq)]
pub struct Coordinate {
pub column: usize,
pub row: usize,
pub column: u8,
pub row: u8,
}
impl Board {

View File

@ -1,5 +1,5 @@
mod api;
pub use api::{CoreApp, Request, Response};
pub use api::{CoreApp, CoreRequest, CoreResponse};
mod types;
pub use types::{BoardError, Color, Size};

View File

@ -27,8 +27,8 @@ pub enum Color {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[typeshare]
pub struct Size {
pub width: usize,
pub height: usize,
pub width: u8,
pub height: u8,
}
impl Default for Size {

View File

@ -1,6 +1,6 @@
use crate::types::{Color, Size};
use crate::{
api::{PlayStoneRequest, Request},
api::{CoreRequest, PlayStoneRequest},
Board, Coordinate,
};
use serde::{Deserialize, Serialize};
@ -36,7 +36,7 @@ impl StoneElement {
#[serde(tag = "type", content = "content")]
pub enum IntersectionElement {
Unplayable,
Empty(Request),
Empty(CoreRequest),
Filled(StoneElement),
}
@ -53,10 +53,9 @@ impl BoardElement {
.map(|row| {
(0..size.width)
.map(|column| {
IntersectionElement::Empty(Request::PlayStoneRequest(PlayStoneRequest {
column,
row,
}))
IntersectionElement::Empty(CoreRequest::PlayStoneRequest(
PlayStoneRequest { column, row },
))
})
.collect::<Vec<IntersectionElement>>()
})
@ -86,7 +85,7 @@ impl From<&Board> for BoardElement {
liberties: None,
color,
}),
None => IntersectionElement::Empty(Request::PlayStoneRequest(
None => IntersectionElement::Empty(CoreRequest::PlayStoneRequest(
PlayStoneRequest { column, row },
)),
})

View File

@ -4,3 +4,4 @@ dev:
test-server:
npx http-server ./dist

View File

@ -1,69 +0,0 @@
/*
Generated by typeshare 1.5.0
*/
export interface PlayStoneRequest {
column: number;
row: number;
}
export interface Size {
width: number;
height: number;
}
export type IntersectionElement =
| { type: "Unplayable", content?: undefined }
| { type: "Empty", content: Request }
| { type: "Filled", content: StoneElement };
export interface BoardElement {
size: Size;
spaces: IntersectionElement[];
}
export enum Color {
Black = "Black",
White = "White",
}
export interface PlayerCardElement {
color: Color;
name: string;
rank: string;
clock: string;
}
export interface ChatElement {
messages: string[];
}
export interface TextFieldElement {
}
export interface PlayingFieldView {
board: BoardElement;
player_card_black: PlayerCardElement;
player_card_white: PlayerCardElement;
chat: ChatElement;
message: TextFieldElement;
current_player: Color;
}
export interface Jitter {
x: number;
y: number;
}
export interface StoneElement {
color: Color;
jitter: Jitter;
}
export type Request =
| { type: "PlayingField", content?: undefined }
| { type: "PlayStoneRequest", content: PlayStoneRequest };
export type Response =
| { type: "PlayingFieldView", content: PlayingFieldView };

View File

@ -1,52 +0,0 @@
import init, { CoreApp } from "kifu-wasm";
const inputField = document.getElementById("input-temp");
const fromUnitField = document.getElementById("input-unit");
const toUnitField = document.getElementById("output-unit");
const outputField = document.getElementById("output-temp");
const form = document.getElementById("converter");
function convertTemp(value, fromUnit, toUnit) {
if (fromUnit === "c") {
if (toUnit === "f") {
return (value * 9) / 5 + 32;
} else if (toUnit === "k") {
return value + 273.15;
}
return value;
}
if (fromUnit === "f") {
if (toUnit === "c") {
return ((value - 32) * 5) / 9;
} else if (toUnit === "k") {
return ((value + 459.67) * 5) / 9;
}
return value;
}
if (fromUnit === "k") {
if (toUnit === "c") {
return value - 273.15;
} else if (toUnit === "f") {
return (value * 9) / 5 - 459.67;
}
return value;
}
throw new Error("Invalid unit");
}
form.addEventListener("input", () => {
const inputTemp = parseFloat(inputField.value);
const fromUnit = fromUnitField.value;
const toUnit = toUnitField.value;
const outputTemp = convertTemp(inputTemp, fromUnit, toUnit);
outputField.value =
Math.round(outputTemp * 100) / 100 + " " + toUnit.toUpperCase();
});
init().then(async () => {
let app = new CoreApp();
console.log("app: ", app, CoreApp);
await app.dispatch({ type: "PlayingField" });
console.log("kifu_wasm successfully initted");
});

View File

@ -0,0 +1,24 @@
import init, { CoreApp } from "kifu-wasm";
import { CoreResponse, CoreRequest, PlayingFieldView } from "core-types";
export class CoreApi {
core: CoreApp;
constructor() {
let app = new CoreApp();
this.core = app;
}
async dispatch(request: CoreRequest): Promise<CoreResponse> {
return await this.core.dispatch(request);
}
async playingField(): Promise<PlayingFieldView> {
return (await this.dispatch({ type: "PlayingField" })).content;
}
}
export const initCore = async (): Promise<CoreApi> => {
await init();
return new CoreApi();
};

View File

@ -1,10 +1,8 @@
import init, { CoreApp } from "kifu-wasm";
import { CoreApi, initCore } from "./coreApi";
const main = async () => {
await init();
let coreApi = new CoreApp();
let response = await coreApi.dispatch({ type: "PlayingField" });
let coreApi = await initCore();
let response = await coreApi.playingField();
console.log("playing field response: ", response);
};

View File

@ -6,9 +6,9 @@ module.exports = {
"kifu-bundle": "./src/main.ts",
sw: "./src/sw.js",
},
loader: {
module: {
rules: [
{ test: /.ts$/, use: "ts-loader", exclude: /node_modules/ },
{ test: /\.ts$/, use: "ts-loader", exclude: /node_modules/ },
{ test: /\.wasm$/, type: "asset/inline" }
],
},
@ -19,5 +19,8 @@ module.exports = {
{ from: "src/converter.css" }
]
})
]
],
resolve: {
extensions: ['.ts'],
}
}

10
package-lock.json generated
View File

@ -7,10 +7,16 @@
"name": "tools",
"workspaces": [
"kifu/ffi/wasm/pkg",
"kifu/core-types",
"kifu/kifu-pwa"
]
},
"kifu/core-types": {
"version": "0.0.1",
"license": "GPL-3.0-or-later"
},
"kifu/ffi/wasm/pkg": {
"name": "kifu-wasm",
"version": "0.1.0"
},
"kifu/kifu-pwa": {
@ -616,6 +622,10 @@
"webpack": "^5.1.0"
}
},
"node_modules/core-types": {
"resolved": "kifu/core-types",
"link": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",

View File

@ -2,6 +2,7 @@
"name": "tools",
"workspaces": [
"kifu/ffi/wasm/pkg",
"kifu/core-types",
"kifu/kifu-pwa"
]
}