A Code Generator to for safe, cross-language API types
~/.cargo/bin
is in your PATH
(run export PATH="$PATH:$HOME/.cargo/bin
)git clone https://gitlab.com/smolamic/transporter.git && cd transporter
cargo install --path .
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.
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.
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.
Because it does not support wilcard paths (variable number of path parameters).
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.
Transporter reads a toml file as input in which types are defined in terms of
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
[string]
), serialized as JSON arrays{string}
), serialized as JSON objectsUser defined types are either
toml
[ alias.Addressbook ]
type = "[Contact]"
In this example the alias "Addressbook" is given to a list of Contacts.
```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,
typeand
number
*
Contact, which also has two fields,
nameand
phone`
Structs are serialized as JSON object ({"name":"John Doe","phone":[...]}
)
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"}}
.
Currently, transporter supports rust und php. In near future, support for Elm and Typescript / Javascript is planned.
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, }, } ```
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 {...} ```