Webwire command-line Interface

Crates.io GitHub Workflow Status

Discord Chat

webwire logo

Webwire is a contract-first API system which features an interface description language a network protocol and code generator for both servers and clients.

This repository contains the the command-line interface used to validate Webwire IDL files and generate code and documentation.

To learn more about webwire in general please visit the documentation repository webwire/webwire-docs.

Example

The following example assumes a Rust server and a TypeScript client. Webwire is by no means limited to those two but those languages show the potential of webwire best.

Given the following IDL file:

```webwire struct HelloRequest { name: String, }

struct HelloResponse { message: String, }

service Hello { hello: HelloRequest -> HelloResponse } ```

The server and client files can be generated using the code generator:

bash $ webwire gen rust < api/chat.ww > server/src/api.rs $ webwire gen ts < api/chat.ww > client/src/api.ts

A Rust server implementation for the given code would look like this:

```rust,ignore use std::net::SocketAddr; use std::sync::{Arc};

use asynctrait::asynctrait;

use ::api::chat;

use ::webwire::server::hyper::MakeHyperService; use ::webwire::server::session::{Auth, AuthError}; use ::webwire::{Response, Router, Server, ConsumerError};

struct ChatService { #[allow(dead_code)] session: Arc, server: Arc>, }

[async_trait]

impl chat::Server for ChatService { async fn send(&self, message: &chat::Message) -> Response> { let client = chat::ClientConsumer(&*self.server); assert!(matches!(client.on_message(message).await, Err(ConsumerError::Broadcast))); Ok(Ok(())) } }

[derive(Default)]

struct Session {}

struct Sessions {}

impl Sessions { pub fn new() -> Self { Self {} } }

[async_trait]

impl webwire::SessionHandler for Sessions { async fn auth(&self, _auth: Option) -> Result { Ok(Session::default()) } async fn connect(&self, _session: &Session) {} async fn disconnect(&self, _session: &Session) {} }

[tokio::main]

async fn main() { // Create session handler let session_handler = Sessions::new();

// Create service router
let router = Arc::new(Router::<Session>::new());

// Create webwire server
let server = Arc::new(webwire::server::Server::new(
    session_handler,
    router.clone(),
));

// Register services
router.service(chat::ServerProvider({
    let server = server.clone();
    move |session| ChatService {
        session,
        server: server.clone(),
    }
}));

// Start hyper service
let addr = SocketAddr::from(([0, 0, 0, 0], 2323));
let make_service = MakeHyperService { server };
let server = hyper::Server::bind(&addr).serve(make_service);

if let Err(e) = server.await {
    eprintln!("server error: {}", e);
}

} ```

A TypeScript client using the generated code would look like that:

```typescript import { Client } from 'webwire' import api from 'api' // this is the generated code

let client = new Client('http://localhost:8000/', [ api.chat.ClientProvider({ async on_message(message) { console.log("Message received:", message) } }) ])

assert(await client.connect())

let chat = api.chat.ServerConsumer(client) let response = await chat.message({ text: "Hello world!" })

assert(response.Ok === null) ```

License

Licensed under either of

at your option.