Crates.io | transporter |
lib.rs | transporter |
version | 0.1.1 |
source | src |
created_at | 2020-09-08 20:34:53.719318 |
updated_at | 2020-09-08 20:51:29.480652 |
description | A code generator for type-safe APIs |
homepage | |
repository | https://gitlab.com/smolamic/transporter/ |
max_upload_size | |
id | 286314 |
size | 150,747 |
A Code Generator to for safe, cross-language API types
~/.cargo/bin
is in your PATH
(run export PATH="$PATH:$HOME/.cargo/bin
)cargo install transporter
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
(string)
)and for otherwise structured data there is also
[string]
), serialized as JSON arrays{string}
), serialized as JSON objectsUser defined types are either
[ alias.Addressbook ]
type = "[Contact]"
In this example the alias "Addressbook" is given to a list of Contacts.
[ 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":[...]}
)
[ 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
type Addressbook = Vec<Contact>;
struct PhoneNumber {
type_: PhoneNumberType,
number: String,
}
struct Contact {
name: String,
phone: Vec<PhoneNumber>,
}
enum PhoneNumberType {
Mobile,
Home,
Custom {
name: String,
},
}
In php the above examples would translate to classes such as
// 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 {...}