# Transporter A Code Generator to for safe, cross-language API types ## Setup * make sure `~/.cargo/bin` is in your `PATH` (run `export PATH="$PATH:$HOME/.cargo/bin`) * `cargo install transporter` ## How it works Transporter is a CLI tool that generates data structures that can easily be serialized and deserialized (mainly to/from JSON) for transmission over http(s) across different languages. ## Why not GraphQL Because you want to avoid rethinking your API entirely from the ground up. In contrast to GraphQL, Transporter is not a query language. All it does is add transport type safety. ## Why not Protocol Buffers Because Protocol Buffers are transmitted in a super space-efficient binary format. Transporter-generated types are transmitted as JSON which you can just read and debug like any other JSON-based API. ## Why not OpenAPI Because it does not support wilcard paths (variable number of path parameters). ## Why not JSON Schema Because there is a huge mess of different versions of the spec, tooling is largely outdated and there's no elegant way to map tagged unions. ## Features Transporter reads a toml file as input in which types are defined in terms of ### Basic Types * string * int * float * bool since transporter types are generally non-nullable, nullable types must be defined as * Optional (denoted as `(string)`) and for otherwise structured data there is also ### Collection Types * List (`[string]`), serialized as JSON arrays * Dict (`{string}`), serialized as JSON objects User defined types are either ### Aliases ```toml [ alias.Addressbook ] type = "[Contact]" ``` In this example the alias "Addressbook" is given to a list of Contacts. ### Structures ```toml [ struct.PhoneNumber ] type = "PhoneNumberType" number = "string" [ struct.Contact ] name = "string" phone = "[PhoneNumber]" ``` In this example two structs are defined * `PhoneNumber`, which has two fields, `type` and `number` * `Contact`, which also has two fields, `name` and `phone` Structs are serialized as JSON object (`{"name":"John Doe","phone":[...]}`) ### Tagged Unions ```toml [ union.PhoneNumberType ] Mobile = {} Home = {} Custom = { name = "string" } ``` In this example a union type is defined. Unions in Transporter are generally tagged unions. An instance of `PhoneNumberType::Mobile` would be serialized as just `"Mobile"`. An instance of `PhoneNumberType::Custom` with name set to `"Work"` would be serialized as `{"Custom":{"name":"Work"}}`. ## Language support Currently, transporter supports rust und php. In near future, support for [Elm](elm-lang.org) and Typescript / Javascript is planned. ### Rust In rust the above examples would roughly (omitting mainly some serde macros) translate to ```rust type Addressbook = Vec; struct PhoneNumber { type_: PhoneNumberType, number: String, } struct Contact { name: String, phone: Vec, } enum PhoneNumberType { Mobile, Home, Custom { name: String, }, } ``` ### PHP In php the above examples would translate to classes such as ```php // Addressbook.php class Addressbook { private $value; public function __construct(array $value) {...} public function get() : array {...} public function set(array $value) {...} public function deserialize($input) : Self {...} } // PhoneNumber.php class PhoneNumber { private $type; private $number; public function __construct(array $fields) {...} public function getType() : PhoneNumberType {...} public function setType(PhoneNumberType $value) {...} public function getNumber() : string {...} public function setNumber(string $value) {...} ... } // Contact.php class Contact {...} // PhoneNumberType.php abstract class PhoneNumberType {...} // PhoneNumberType/Mobile.php class Mobile extends PhoneNumberType {...} // PhoneNumberType/Home.php class Home extends PhoneNumberType {...} // PhoneNumberType/Custom.php class Custom extends PhoneNumberType {...} ```