# zits
**Compatible with:**
- **HDK v0.3.0**
- **@Holochain/client v0.17.0-dev.7**
- **@holochain-open-dev/core-types v0.7.0**
- **@ddd-qc/cell-proxy v0.23.0**
A utility to generate Typescript bindings for Zome code in Rust (**Z**ome **I**nto **T**ype**S**cript).
# Install
The CLI can be installed from [crates.io](https://crates.io):
```
cargo install zits
```
Or by building the source-code locally:
```
git clone https://github.com/ddd-mtl/zits.git
cd zits
cargo install --path ./
```
# Usage
**No modification of the zome rust code is required!**
Use the CLI tool on the folders of your zome code:
```sh
zits -i ./zomes/profiles -i ./zomes/profiles_integrity -o ./bindings/profiles.ts
```
Typescript bindings will be generated for all types, structs, enums, and consts marked with holochain or serde specific attributes (`#[hdk_entry_helper]`, `#[hdk_entry_defs]`, etc). The bindings file will be named `*.types.ts`.
Bindings will also be generated for public consts that don't have those attributes.
The serde `rename_all` attribute argument is supported.
All functions marked with holochain attributes `#[hdk_extern]`, except the Holochain callbacks, will be listed in a typescript array to be consumed by Holochain's credential authorizing mechanism. The array will be written in a file named `*.fn.ts`.
A `ZomeProxy` subclass for [cell-proxy](https://npmjs.org/@ddd-qc/cell-proxy) will be generated in its own file. It will have a method for each function marked with `[hdk_extern]`, excluding the holochain callbacks like `init()` or `validate()`. It will be named after the filename given as output. The file will also have the same name with `*.proxy.ts` as extension.
**Optional Rust Attributes for zome functions**
- `#[ignore(zits)]`: Tells zits to skip this zome function when generating the `ZomeProxy` and function list.
- `#[feature(zits_blocking)]`: Tells zits to generate a blocking call in the `ZomeProxy` for this zome function.
## Multiple Inputs
You can specify many inputs (directories and/or files) using the `-i` flag multiple times, like so:
```sh
zits -i directory1 -i directory2 -o types.ts
```
## Multiple Outputs
It might help to create multiple typing files for your project. It's easy, just call zits multiple times:
```sh
zits -i src/models -o models.ts
zits -i src/api -o api.ts
```
# Usage as a library
In the case that installing the `zits` CLI isn't an option, you can use it as a library:
1. Add the library to your project:
```sh
cargo add zits@1
```
2. Create a new binary in your project which uses the crate (for example, `bin/zits.rs`):
```rust
// bin/zits.rs
use std::path::PathBuf;
pub fn main() {
let dir = env!("CARGO_MANIFEST_DIR");
let inputs = vec![PathBuf::from_iter([dir, "backend"])];
let output = PathBuf::from_iter([dir, "frontend/src/types/rust.ts"]);
zits::generate_typescript_defs(inputs, output, false);
}
```
3. Create a `Cargo.toml` binary entry:
```toml
[[bin]]
name = "zits"
path = "bin/zits.rs"
```
4. Execute!
```sh
cargo run --bin zits
```
**Protip**: to use `cargo zits`, create an alias in `.cargo/config`:
```toml
[alias]
zits="run --bin zits"
```
# Errors
A list of files which can't be opened or parsed successfully are listed after executing `zits`. For other errors, try using the `--debug` flag to pinpoint issues. Please use the Github issue tracker to report any issues.
# Docs
See `zits --help` for more information on parameters, options & flags.
# Supported Conversions & Examples
`zits` is a fork of [tsync](https://github.com/wulf/tsync). See its documentations for details on how conversions works.
Support added for types defined in `@holochain/client` and `@holochain-open-dev/core-types`.
## Types
Support includes, but is not limited to, the following "base" types:
- `ExternResult` converts to `Promise`
- `BTreeMap` converts to `Record`
- `Result` converts to `A | B`
- `X25519PubKey` converts to `Uint8Array`
**Holochain's `Record` and `RecordEntry` types are renamed `HcRecord` and `HcRecordEntry` respectively as to not conflict with typescript's native `Record` utility type.**
## Functions
Support has been added for functions, but only the first argument is considered since as this is a limitation of zome functions.
- `Option` converts to `T | null` when it's a function return type
- A destructured argument will be converted to `input`
## Structs
Added support for non-tuple newtypes.
### Example
Input:
```rust
#[serde]
pub struct GetMailOutput(pub Option>);
```
Output:
```javascript
export type GetMailOutput = number | string | null;
```
## Enums
Additionnaly support for enums of unnamed variants has been added and converts to a string enum and a ORed type.
### Example
#### unnamed variants
Input:
```rust
#[hdk_entry_defs]
pub enum PlaysetEntry {
SvgMarker(SvgMarker),
EmojiGroup(EmojiGroup),
Template(Template),
Space,
}
```
Output:
```javascript
export enum PlaysetEntryType {
SvgMarker = 'SvgMarker',
EmojiGroup = 'EmojiGroup',
Template = 'Template',
Space = 'Space',
}
export type PlaysetEntryVariantSvgMarker = {svgMarker: SvgMarker}
export type PlaysetEntryVariantEmojiGroup = {emojiGroup: EmojiGroup}
export type PlaysetEntryVariantTemplate = {template: Template}
export type PlaysetEntryVariantSpace = {space: null}
export type PlaysetEntry =
| PlaysetEntryVariantSvgMarker | PlaysetEntryVariantEmojiGroup | PlaysetEntryVariantTemplate | PlaysetEntryVariantSpace;
```
#### tagged unnamed variants
Serde's tag and content attributes are considered for enums. When provided, type declarations for each variant is omitted.
Input:
```rust
#[serde(tag = "type", content = "content")]
pub enum Message {
Ping(AgentPubKeyB64),
Pong(AgentPubKeyB64),
NewHere(HereOutput),
DeleteHere((EntryHashB64, ActionHashB64)), /// sessionEh, hereLinkHh
UpdateHere((u32, ActionHashB64, Here)), ///[index, newLinkAh, newHereEntry]}
NewSession((EntryHashB64, PlacementSession)),
/// - with entry hash of entries
NewSpace(EntryHashB64),
NewTemplate(EntryHashB64),
NewSvgMarker(EntryHashB64),
NewEmojiGroup(EntryHashB64),
}
```
Output:
```javascript
export enum MessageType {
Ping = 'Ping',
Pong = 'Pong',
NewHere = 'NewHere',
DeleteHere = 'DeleteHere',
UpdateHere = 'UpdateHere',
}
export type Message =
| {type: {Ping: null}, content: AgentPubKeyB64}
| {type: {Pong: null}, content: AgentPubKeyB64}
| {type: {NewHere: null}, content: HereOutput}
| {type: {DeleteHere: null}, content: [EntryHashB64, ActionHashB64]}
| {type: {UpdateHere: null}, content: [number, ActionHashB64, Here]}
```
# Development/Testing
Use `./test/test_all.sh` to run tests.
After running the test, there should be no unexpected changes to files in `./test` (use `git status` and `git diff` to see if there were any changes).
# License
This tool is distributed under the terms of both the MIT license and the Apache License (Version 2.0).
See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details.