Skip to main content

vercel_rpc_cli/
model.rs

1use std::fmt;
2use std::path::PathBuf;
3
4use serde::{Deserialize, Serialize};
5
6/// The kind of RPC procedure, determined by the macro attribute.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "lowercase")]
9pub enum ProcedureKind {
10    Query,
11    Mutation,
12}
13
14/// A single Rust type reference extracted from source code.
15///
16/// Preserves the full path as written (e.g. `Vec<String>`, `MyStruct`).
17/// Generic parameters are stored recursively for accurate TS mapping.
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct RustType {
20    /// The base type name (e.g. "Vec", "String", "MyStruct")
21    pub name: String,
22    /// Generic type parameters, if any (e.g. `Vec<String>` → [RustType("String")])
23    pub generics: Vec<RustType>,
24}
25
26impl RustType {
27    /// Creates a simple type with no generic parameters (e.g. `String`, `i32`).
28    pub fn simple(name: impl Into<String>) -> Self {
29        Self {
30            name: name.into(),
31            generics: vec![],
32        }
33    }
34
35    /// Creates a generic type with the given type parameters (e.g. `Vec<String>`).
36    pub fn with_generics(name: impl Into<String>, generics: Vec<RustType>) -> Self {
37        Self {
38            name: name.into(),
39            generics,
40        }
41    }
42}
43
44impl fmt::Display for RustType {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        write!(f, "{}", self.name)?;
47        if !self.generics.is_empty() {
48            write!(f, "<")?;
49            for (i, g) in self.generics.iter().enumerate() {
50                if i > 0 {
51                    write!(f, ", ")?;
52                }
53                write!(f, "{g}")?;
54            }
55            write!(f, ">")?;
56        }
57        Ok(())
58    }
59}
60
61/// Metadata for a single RPC procedure extracted from a source file.
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct Procedure {
64    /// Procedure name derived from the function name
65    pub name: String,
66    /// Query or Mutation
67    pub kind: ProcedureKind,
68    /// Input parameter type; `None` means no input (unit type)
69    pub input: Option<RustType>,
70    /// Return type; `None` means unit return
71    pub output: Option<RustType>,
72    /// Source file this procedure was extracted from
73    pub source_file: PathBuf,
74    /// Doc comment extracted from `///` lines
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub docs: Option<String>,
77}
78
79/// All user-defined struct types found in the scanned source files.
80/// Needed for generating corresponding TypeScript interfaces.
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct StructDef {
83    /// Struct name
84    pub name: String,
85    /// Named fields with their types
86    pub fields: Vec<(String, RustType)>,
87    /// Source file this struct was defined in
88    pub source_file: PathBuf,
89    /// Doc comment extracted from `///` lines
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub docs: Option<String>,
92}
93
94/// A single variant of a Rust enum.
95#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct EnumVariant {
97    /// Variant name (e.g. `Active`, `Error`)
98    pub name: String,
99    /// Variant kind determines TypeScript representation
100    pub kind: VariantKind,
101}
102
103/// The shape of an enum variant's data.
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub enum VariantKind {
106    /// Unit variant: `Active` → string literal `"Active"`
107    Unit,
108    /// Tuple variant with a single unnamed field: `Error(String)` → `{ Error: string }`
109    Tuple(Vec<RustType>),
110    /// Struct variant with named fields: `User { name: String }` → `{ User: { name: string } }`
111    Struct(Vec<(String, RustType)>),
112}
113
114/// All user-defined enum types found in the scanned source files.
115/// Needed for generating corresponding TypeScript union types.
116#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct EnumDef {
118    /// Enum name
119    pub name: String,
120    /// Variants of the enum
121    pub variants: Vec<EnumVariant>,
122    /// Source file this enum was defined in
123    pub source_file: PathBuf,
124    /// Doc comment extracted from `///` lines
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub docs: Option<String>,
127}
128
129/// Complete manifest of all discovered RPC metadata from a scan.
130#[derive(Debug, Clone, Default, Serialize, Deserialize)]
131pub struct Manifest {
132    pub procedures: Vec<Procedure>,
133    pub structs: Vec<StructDef>,
134    pub enums: Vec<EnumDef>,
135}