4 releases
0.0.4 | Mar 19, 2024 |
---|---|
0.0.3 | Mar 19, 2024 |
0.0.2 | Mar 19, 2024 |
0.0.1 | Mar 19, 2024 |
#272 in Procedural macros
37KB
807 lines
convex-macros
Macros to help make Convex in Rust nice
Installation
[dependencies]
ragkit_convex_macros = "0.0.4"
# Required by code this macro generates.
anyhow = "1.0.80"
convex = "0.6.0"
serde = "1.0.185"
serde_json = "1.0"
Usage
Create models using the same Convex validator syntax as your schema definition.
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
.
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),
);
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
.
Validator List
Validator Name | Rust Type | Notes |
---|---|---|
v.string() |
String |
|
v.id("tableName") |
String |
Ids are not validated against your tables |
v.null() |
() |
|
v.int64() |
i64 |
|
v.number() |
f64 |
|
v.boolean() |
bool |
|
v.optional(...) |
Option<T> |
|
v.union(...) |
Generated enum |
|
v.object({field: ...}) |
Generated struct |
Field names can't be rust keywords (like type ) |
v.bytes() |
not implemented | |
v.array(values) |
not implemented | |
v.any() |
not implemented |
Limitations
- This is experimental and may not be "production quality", use with caution.
v.bytes()
,v.array()
,v.any()
are not yet supported.- Field names must be valid Rust identifiers, so keywords like
type
cannot be a field name. Map it to_type
,kind
,t
, etc. - Union variant names are always named like:
Variant1
,Variant2
, etc. - The first acceptable union branch will be used if there are multiples that could validly parse data.
- This package generates code that expects
anyhow
,convex
,serde
, andserde_json
to be available. - Ints and Floats may be coerced into each other. Please test out your use cases and open an issue if you believe the behavior should change.
License
MIT
Dependencies
~245–690KB
~16K SLoC