KyleK
Convex Community2y ago
9 replies
Kyle

Rust Macro: convex_model!

https://github.com/ragkit/convex-macros

I've been using the Convex Rust client and found working with nested objects a bit cumbersome. I made a macro that creates native Rust structs and enums based on a Typescript schema definition. Then you can build it from convex::Value and serialize it to serde_json::Value automatically.

convex_model!(User {
  _id: v.id("users"),
  name: v.string(),
  age: v.optional(v.int64()),
  platform: v.union(
    v.object({
      platform: v.literal("google"),
      verified: v.boolean(),
    }),
    v.object({
      platform: v.literal("github"),
      username: v.string(),
    }),
  ),
});


This generates pub struct User {} with various methods to convert from convex::Value and to serde_json::Value.

// This is the shape you might get from a convex function you've defined.
let user = User::from_convex_value(&Value::Object(btreemap! {
  "_id".into() => Value::String("1234".into()),
  "name".into() => Value::String("Alice".into()),
  "age".into() => Value::Int64(42),
  "platform".into() => Value::Object(btreemap! {
    "platform".into() => Value::String("github".into()),
    "username".into() => Value::String("alicecodes".into()),
  }),
}))
.expect("it should parse");

assert_eq!("1234", user._id);
assert_eq!("alicecodes", user.platform.as_2().unwrap().username);
assert_eq!(
  json!({
    "_id": "1234",
    "name": "Alice",
    "age": 42,
    "platform": {
      "platform": "github",
      "username": "alicecodes",
    },
  }),
  json!(user),
);


Some Features:

- let user = User::from_convex_value(value)?; to parse a value from Convex client.
- json!(user) to serialize as json.
- Discriminated unions are automatically handled.
- Helper functions for each union branch: user.platform.as_2()?.username.
GitHub
Macros to help make Convex in Rust nice. Contribute to ragkit/convex-macros development by creating an account on GitHub.
GitHub - ragkit/convex-macros: Macros to help make Convex in Rust nice
A value that can be passed as an argument or returned from Convex functions. They correspond to the supported Convex types.
Was this page helpful?