djkato
djkato

Reputation: 736

How to handle custom events callback type with add_event_listener_with_callback()

I'm not sure how to handle a custom event with web_sys/wasm_bindgen. This is how it's handled in TypeScript.

window.addEventListener(
  "message",
  ({ origin, data }: Omit<MessageEvent, "data"> & { data: Events }) => {
    console.log(data.type) // "handshake"
    console.log(data.payload) // {token:"",version:""}
    console.log(origin) // "https://dash.site.com"
  }
)

type Event<Name extends EventType, Payload extends {}> = {
  payload: Payload;
  type: Name;
};

type Events =
  | HandshakeEvent
  | DispatchResponseEvent
//| ...

type HandshakeEvent = Event<
  "handshake",
  {
    token: string;
    version: Version;
    saleorVersion?: string;
    dashboardVersion?: string;
  }>

type DispatchResponseEvent = Event<
  "response",
  {
    actionId: string;
    ok: boolean;
  }>

This is what I got in Rust:

#[derive(Deserialize, Serialize, Debug)]
#[serde(tag = "type", content = "payload")]
#[serde(rename_all = "camelCase")]
pub enum Event {
    Handshake(PayloadHanshake),
    Response(PayloadResponse),
    //...
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PayloadHanshake {
    pub token: String,
    pub version: String,
    pub saleor_version: Option<String>,
    pub dashboard_version: Option<String>,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PayloadResponse {
    pub action_id: String,
    pub ok: bool,
}

fn listen() -> Result<_,_> {
    let window = web_sys::window()?;
    let cb = Closure::wrap(Box::new(|e: ????????? | ()) as Box<dyn FnMut(_)>);
    window.add_event_listener_with_callback("message", &cb.as_ref().unchecked_ref());
}

But I'm unsure how to handle that event type. What should es type be? Data is of type Events, which can have one of many types of payloads. For example the event can receive:

{
  origin: "https://dash.site.com",
  data: {
    type: "handshake", // This defines the payload type, `adjacently tagged enum` in serde
    payload: { // Can have many different fields
      token: "aaaaa",
      version: 1,
      saleorVersion: "3.0",
      dashboardVersion: "3.1",
    },
  },
}

I know how to serde serialize this as JSON, but I don't know how to do this in this event. Is there some generic JavaScript object type in web_sys I can try to serialize part by part?

Upvotes: 0

Views: 130

Answers (0)

Related Questions