Skip to main content

prax_typegen/
mapping.rs

1//! Type mapping from Prax scalar types to TypeScript and Zod types.
2
3use prax_schema::ScalarType;
4
5/// Maps Prax types to TypeScript / Zod representations.
6pub struct TypeMapper;
7
8impl TypeMapper {
9    /// Map a Prax scalar type to its TypeScript type string.
10    pub fn ts_type(scalar: &ScalarType) -> &'static str {
11        match scalar {
12            ScalarType::Int => "number",
13            ScalarType::BigInt => "bigint",
14            ScalarType::Float => "number",
15            ScalarType::Decimal => "string",
16            ScalarType::String => "string",
17            ScalarType::Boolean => "boolean",
18            ScalarType::DateTime => "Date",
19            ScalarType::Date => "string",
20            ScalarType::Time => "string",
21            ScalarType::Json => "unknown",
22            ScalarType::Bytes => "Uint8Array",
23            ScalarType::Uuid => "string",
24            ScalarType::Cuid | ScalarType::Cuid2 | ScalarType::NanoId | ScalarType::Ulid => {
25                "string"
26            }
27            ScalarType::Vector(_) | ScalarType::HalfVector(_) => "number[]",
28            ScalarType::SparseVector(_) => "Array<[number, number]>",
29            ScalarType::Bit(_) => "Uint8Array",
30        }
31    }
32
33    /// Map a Prax scalar type to its Zod schema expression.
34    pub fn zod_type(scalar: &ScalarType) -> &'static str {
35        match scalar {
36            ScalarType::Int => "z.number().int()",
37            ScalarType::BigInt => "z.bigint()",
38            ScalarType::Float => "z.number()",
39            ScalarType::Decimal => "z.string()",
40            ScalarType::String => "z.string()",
41            ScalarType::Boolean => "z.boolean()",
42            ScalarType::DateTime => "z.coerce.date()",
43            ScalarType::Date => "z.string().date()",
44            ScalarType::Time => "z.string().time()",
45            ScalarType::Json => "z.unknown()",
46            ScalarType::Bytes => "z.instanceof(Uint8Array)",
47            ScalarType::Uuid => "z.string().uuid()",
48            ScalarType::Cuid => "z.string().cuid()",
49            ScalarType::Cuid2 => "z.string().cuid2()",
50            ScalarType::NanoId => "z.string().nanoid()",
51            ScalarType::Ulid => "z.string().ulid()",
52            ScalarType::Vector(_) | ScalarType::HalfVector(_) => "z.array(z.number())",
53            ScalarType::SparseVector(_) => "z.array(z.tuple([z.number(), z.number()]))",
54            ScalarType::Bit(_) => "z.instanceof(Uint8Array)",
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_ts_scalars() {
65        assert_eq!(TypeMapper::ts_type(&ScalarType::Int), "number");
66        assert_eq!(TypeMapper::ts_type(&ScalarType::BigInt), "bigint");
67        assert_eq!(TypeMapper::ts_type(&ScalarType::String), "string");
68        assert_eq!(TypeMapper::ts_type(&ScalarType::Boolean), "boolean");
69        assert_eq!(TypeMapper::ts_type(&ScalarType::DateTime), "Date");
70        assert_eq!(TypeMapper::ts_type(&ScalarType::Json), "unknown");
71        assert_eq!(TypeMapper::ts_type(&ScalarType::Uuid), "string");
72        assert_eq!(TypeMapper::ts_type(&ScalarType::Decimal), "string");
73        assert_eq!(TypeMapper::ts_type(&ScalarType::Bytes), "Uint8Array");
74        assert_eq!(
75            TypeMapper::ts_type(&ScalarType::Vector(Some(128))),
76            "number[]"
77        );
78    }
79
80    #[test]
81    fn test_zod_scalars() {
82        assert_eq!(TypeMapper::zod_type(&ScalarType::Int), "z.number().int()");
83        assert_eq!(TypeMapper::zod_type(&ScalarType::String), "z.string()");
84        assert_eq!(TypeMapper::zod_type(&ScalarType::Uuid), "z.string().uuid()");
85        assert_eq!(
86            TypeMapper::zod_type(&ScalarType::DateTime),
87            "z.coerce.date()"
88        );
89        assert_eq!(TypeMapper::zod_type(&ScalarType::BigInt), "z.bigint()");
90    }
91
92    #[test]
93    fn test_id_types_are_strings() {
94        assert_eq!(TypeMapper::ts_type(&ScalarType::Cuid), "string");
95        assert_eq!(TypeMapper::ts_type(&ScalarType::Cuid2), "string");
96        assert_eq!(TypeMapper::ts_type(&ScalarType::NanoId), "string");
97        assert_eq!(TypeMapper::ts_type(&ScalarType::Ulid), "string");
98    }
99}