prisma_rust_schema/
dmmf.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Deserialize, Serialize)]
5pub struct Document {
6    pub datamodel: Datamodel,
7    pub schema: Schema,
8    pub mappings: Mappings,
9}
10
11#[derive(Debug, Clone, Deserialize, Serialize)]
12pub struct Mappings {
13    #[serde(rename = "modelOperations")]
14    pub model_operations: Vec<ModelMapping>,
15    #[serde(rename = "otherOperations")]
16    pub other_operations: OtherOperationMappings,
17}
18
19#[derive(Debug, Clone, Deserialize, Serialize)]
20pub struct OtherOperationMappings {
21    pub read: Vec<String>,
22    pub write: Vec<String>,
23}
24
25#[derive(Debug, Clone, Deserialize, Serialize)]
26pub struct DatamodelEnum {
27    pub name: String,
28    pub values: Vec<EnumValue>,
29    #[serde(rename = "dbName")]
30    pub db_name: Option<String>,
31    pub documentation: Option<String>,
32}
33
34#[derive(Debug, Clone, Deserialize, Serialize)]
35pub struct SchemaEnum {
36    pub name: String,
37    pub values: Vec<String>,
38}
39
40#[derive(Debug, Clone, Deserialize, Serialize)]
41pub struct EnumValue {
42    pub name: String,
43    #[serde(rename = "dbName")]
44    pub db_name: Option<String>,
45}
46
47#[derive(Debug, Clone, Deserialize, Serialize)]
48pub struct Datamodel {
49    pub models: Vec<Model>,
50    pub enums: Vec<DatamodelEnum>,
51    #[serde(rename = "types")]
52    pub type_models: Vec<Model>,
53    pub indexes: Vec<Index>,
54}
55
56#[derive(Debug, Clone, Deserialize, Serialize)]
57pub struct UniqueIndex {
58    pub name: String,
59    pub fields: Vec<String>,
60}
61
62#[derive(Debug, Clone, Deserialize, Serialize)]
63pub struct PrimaryKey {
64    pub name: Option<String>,
65    pub fields: Vec<String>,
66}
67
68#[derive(Debug, Clone, Deserialize, Serialize)]
69#[serde(rename_all = "camelCase")]
70pub struct Model {
71    pub name: String,
72    pub db_name: Option<String>,
73    pub schema: Option<String>,
74    pub fields: Vec<Field>,
75    pub unique_fields: Vec<Vec<String>>,
76    pub unique_indexes: Vec<UniqueIndex>,
77    pub documentation: Option<String>,
78    pub primary_key: Option<PrimaryKey>,
79    pub is_generated: Option<bool>,
80}
81
82#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
83#[serde(rename_all = "lowercase")]
84pub enum FieldKind {
85    Scalar,
86    Object,
87    Enum,
88    Unsupported,
89}
90
91#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
92#[serde(rename_all = "lowercase")]
93pub enum FieldNamespace {
94    Model,
95    Prisma,
96}
97
98#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
99#[serde(rename_all = "camelCase")]
100pub enum FieldLocation {
101    Scalar,
102    InputObjectTypes,
103    OutputObjectTypes,
104    EnumTypes,
105    FieldRefTypes,
106}
107
108impl AsRef<str> for FieldLocation {
109    fn as_ref(&self) -> &str {
110        match self {
111            FieldLocation::Scalar => "scalar",
112            FieldLocation::InputObjectTypes => "inputObjectTypes",
113            FieldLocation::OutputObjectTypes => "outputObjectTypes",
114            FieldLocation::EnumTypes => "enumTypes",
115            FieldLocation::FieldRefTypes => "fieldRefTypes",
116        }
117    }
118}
119
120#[derive(Debug, Clone, Deserialize, Serialize)]
121#[serde(rename_all = "camelCase")]
122pub struct Field {
123    pub kind: FieldKind,
124    pub name: String,
125    pub is_required: bool,
126    pub is_list: bool,
127    pub is_unique: bool,
128    pub is_id: bool,
129    pub is_read_only: bool,
130    pub is_generated: Option<bool>,
131    pub is_updated_at: Option<bool>,
132    #[serde(rename = "type")]
133    pub field_type: String,
134    /// [string | string[]]
135    pub native_type: Option<Vec<Value>>,
136    pub db_name: Option<String>,
137    pub has_default_value: bool,
138    #[serde(rename = "default")]
139    pub default_value: Option<FieldDefaultValue>,
140    pub relation_from_fields: Option<Vec<String>>,
141    pub relation_to_fields: Option<Vec<String>>,
142    pub relation_on_delete: Option<String>,
143    pub relation_on_update: Option<String>,
144    pub relation_name: Option<String>,
145    pub documentation: Option<String>,
146}
147
148#[derive(Debug, Clone, Deserialize, Serialize)]
149#[serde(untagged)]
150pub enum FieldDefaultValue {
151    Object(FieldDefault),
152    Scalar(FieldDefaultScalar),
153    ScalarList(Vec<FieldDefaultScalar>),
154}
155
156#[derive(Debug, Clone, Deserialize, Serialize)]
157pub struct FieldDefault {
158    pub name: String,
159    /// Can be a string or number
160    pub args: Vec<Value>,
161}
162
163/// String, bool, or number
164pub type FieldDefaultScalar = Value;
165
166#[derive(Debug, Clone, Deserialize, Serialize)]
167#[serde(rename_all = "camelCase")]
168pub struct Index {
169    pub model: String,
170    #[serde(rename = "type")]
171    pub index_type: IndexType,
172    pub is_defined_on_field: bool,
173    pub name: Option<String>,
174    pub db_name: Option<String>,
175    pub algorithm: Option<String>,
176    pub clustered: Option<bool>,
177    pub fields: Vec<IndexField>,
178}
179
180#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
181#[serde(rename_all = "lowercase")]
182pub enum IndexType {
183    Id,
184    Normal,
185    Unique,
186    Fulltext,
187}
188
189#[derive(Debug, Clone, Deserialize, Serialize)]
190#[serde(rename_all = "camelCase")]
191pub struct IndexField {
192    pub name: String,
193    pub sort_order: Option<SortOrder>,
194    pub length: Option<u32>,
195    pub operator_class: Option<String>,
196}
197
198#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
199#[serde(rename_all = "lowercase")]
200pub enum SortOrder {
201    Asc,
202    Desc,
203}
204
205#[derive(Debug, Clone, Deserialize, Serialize)]
206#[serde(rename_all = "camelCase")]
207pub struct Schema {
208    pub root_query_type: Option<String>,
209    pub root_mutation_type: Option<String>,
210    pub input_object_types: InputObjectTypes,
211    pub output_object_types: OutputObjectTypes,
212    pub enum_types: EnumTypes,
213    pub field_ref_types: FieldRefTypes,
214}
215
216#[derive(Debug, Clone, Deserialize, Serialize)]
217pub struct InputObjectTypes {
218    pub model: Option<Vec<InputType>>,
219    pub prisma: Vec<InputType>,
220}
221
222#[derive(Debug, Clone, Deserialize, Serialize)]
223pub struct OutputObjectTypes {
224    pub model: Vec<OutputType>,
225    pub prisma: Vec<OutputType>,
226}
227
228#[derive(Debug, Clone, Deserialize, Serialize)]
229pub struct EnumTypes {
230    pub model: Option<Vec<SchemaEnum>>,
231    pub prisma: Vec<SchemaEnum>,
232}
233
234#[derive(Debug, Clone, Deserialize, Serialize)]
235pub struct FieldRefTypes {
236    pub prisma: Option<Vec<FieldRefType>>,
237}
238
239#[derive(Debug, Clone, Deserialize, Serialize)]
240pub struct Query {
241    pub name: String,
242    pub args: Vec<SchemaArg>,
243    pub output: QueryOutput,
244}
245
246#[derive(Debug, Clone, Deserialize, Serialize)]
247#[serde(rename_all = "camelCase")]
248pub struct QueryOutput {
249    pub name: String,
250    pub is_required: bool,
251    pub is_list: bool,
252}
253
254#[derive(Debug, Clone, Deserialize, Serialize)]
255#[serde(rename_all = "camelCase")]
256pub struct TypeRef<T: AsRef<str>> {
257    pub is_list: bool,
258    #[serde(rename = "type")]
259    pub type_name: String,
260    pub location: T,
261    pub namespace: Option<FieldNamespace>,
262}
263
264pub type InputTypeRef = TypeRef<FieldLocation>;
265
266#[derive(Debug, Clone, Deserialize, Serialize)]
267#[serde(rename_all = "camelCase")]
268pub struct SchemaArg {
269    pub name: String,
270    pub comment: Option<String>,
271    pub is_nullable: bool,
272    pub is_required: bool,
273    pub input_types: Vec<InputTypeRef>,
274    pub deprecation: Option<Deprecation>,
275}
276
277#[derive(Debug, Clone, Deserialize, Serialize)]
278pub struct OutputType {
279    pub name: String,
280    pub fields: Vec<SchemaField>,
281}
282
283#[derive(Debug, Clone, Deserialize, Serialize)]
284#[serde(rename_all = "camelCase")]
285pub struct SchemaField {
286    pub name: String,
287    pub is_nullable: Option<bool>,
288    pub output_type: OutputTypeRef,
289    pub args: Vec<SchemaArg>,
290    pub deprecation: Option<Deprecation>,
291    pub documentation: Option<String>,
292}
293
294#[derive(Debug, Clone, Deserialize, Serialize)]
295#[serde(rename_all = "camelCase")]
296pub struct OutputTypeRef {
297    pub is_list: bool,
298    #[serde(rename = "type")]
299    pub type_name: String,
300    pub location: FieldLocation,
301}
302
303#[derive(Debug, Clone, Deserialize, Serialize)]
304#[serde(rename_all = "camelCase")]
305pub struct Deprecation {
306    pub since_version: String,
307    pub reason: String,
308    pub planned_removal_version: Option<String>,
309}
310
311#[derive(Debug, Clone, Deserialize, Serialize)]
312pub struct InputType {
313    pub name: String,
314    pub constraints: InputTypeConstraints,
315    pub meta: Option<InputTypeMeta>,
316    pub fields: Vec<SchemaArg>,
317}
318
319#[derive(Debug, Clone, Deserialize, Serialize)]
320#[serde(rename_all = "camelCase")]
321pub struct InputTypeConstraints {
322    pub max_num_fields: Option<u32>,
323    pub min_num_fields: Option<u32>,
324    pub fields: Option<Vec<String>>,
325}
326
327#[derive(Debug, Clone, Deserialize, Serialize)]
328pub struct InputTypeMeta {
329    pub source: Option<String>,
330    pub grouping: Option<String>,
331}
332
333#[derive(Debug, Clone, Deserialize, Serialize)]
334#[serde(rename_all = "camelCase")]
335pub struct FieldRefType {
336    pub name: String,
337    pub allow_types: Vec<TypeRef<FieldLocation>>,
338    pub fields: Vec<SchemaArg>,
339}
340
341#[derive(Debug, Clone, Deserialize, Serialize)]
342#[serde(rename_all = "camelCase")]
343pub struct ModelMapping {
344    pub model: String,
345    /// This is not optional in @prisma/dmmf, but can be None in the Generator DMMF
346    pub plural: Option<String>,
347    pub find_unique: Option<String>,
348    pub find_unique_or_throw: Option<String>,
349    pub find_first: Option<String>,
350    pub find_first_or_throw: Option<String>,
351    pub find_many: Option<String>,
352    pub create: Option<String>,
353    pub create_many: Option<String>,
354    pub create_many_and_return: Option<String>,
355    pub update: Option<String>,
356    pub update_many: Option<String>,
357    pub update_many_and_return: Option<String>,
358    pub upsert: Option<String>,
359    pub delete: Option<String>,
360    pub delete_many: Option<String>,
361    pub aggregate: Option<String>,
362    pub group_by: Option<String>,
363    pub count: Option<String>,
364    pub find_raw: Option<String>,
365    pub aggregate_raw: Option<String>,
366}
367
368#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
369#[serde(rename_all = "camelCase")]
370pub enum ModelAction {
371    FindUnique,
372    FindUniqueOrThrow,
373    FindFirst,
374    FindFirstOrThrow,
375    FindMany,
376    Create,
377    CreateMany,
378    CreateManyAndReturn,
379    Update,
380    UpdateMany,
381    UpdateManyAndReturn,
382    Upsert,
383    Delete,
384    DeleteMany,
385    GroupBy,
386    /// Unused
387    Count,
388    Aggregate,
389    FindRaw,
390    AggregateRaw,
391}
392
393impl From<&Field> for String {
394    fn from(field: &Field) -> Self {
395        // camelCase to snake_case
396        let field_name = field
397            .name
398            .clone()
399            .chars()
400            .fold(String::new(), |mut acc, c| {
401                if c.is_uppercase() {
402                    if !acc.is_empty() {
403                        acc.push('_');
404                    }
405                    acc.push(c.to_ascii_lowercase());
406                } else {
407                    acc.push(c);
408                }
409                acc
410            });
411        let mut field_type = String::new();
412        let t = match field.field_type.as_str() {
413            "String" => "String".to_string(),
414            "Int" => "i32".to_string(),
415            "Float" => "f64".to_string(),
416            "Boolean" => "bool".to_string(),
417            "DateTime" => "chrono::NaiveDateTime".to_string(),
418            _ => field.field_type.clone(),
419        };
420
421        if !field.is_required {
422            field_type.push_str("Option<");
423        }
424        if field.is_list {
425            field_type.push_str("Vec<");
426        }
427
428        field_type.push_str(&t);
429
430        if field.is_list {
431            field_type.push('>');
432        }
433        if !field.is_required {
434            field_type.push('>');
435        }
436
437        format!("{:>4}pub {}: {},\n", "", field_name, field_type)
438    }
439}