Skip to main content

fraiseql_cli/schema/intermediate/
fragments.rs

1//! Fragment/directive structs: `IntermediateFragment`, `IntermediateFragmentField`,
2//! `IntermediateFragmentFieldDef`, `IntermediateDirective`, `IntermediateAppliedDirective`.
3
4use serde::{Deserialize, Serialize};
5
6use super::operations::IntermediateArgument;
7
8// =============================================================================
9// Fragment and Directive Definitions (GraphQL Spec §2.9-2.12)
10// =============================================================================
11
12/// Fragment definition in intermediate format.
13///
14/// Fragments are reusable field selections that can be spread into queries.
15/// Per GraphQL spec §2.9-2.10, fragments have a type condition and field list.
16///
17/// # Example JSON
18///
19/// ```json
20/// {
21///   "name": "UserFields",
22///   "on": "User",
23///   "fields": ["id", "name", "email"]
24/// }
25/// ```
26#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
27pub struct IntermediateFragment {
28    /// Fragment name (e.g., "UserFields")
29    pub name: String,
30
31    /// Type condition - the type this fragment applies to (e.g., "User")
32    #[serde(rename = "on")]
33    pub type_condition: String,
34
35    /// Fields to select (can be field names or nested fragment spreads)
36    pub fields: Vec<IntermediateFragmentField>,
37
38    /// Fragment description (from docstring)
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub description: Option<String>,
41}
42
43/// Fragment field selection - either a simple field or a nested object/fragment spread.
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(untagged)]
46#[non_exhaustive]
47pub enum IntermediateFragmentField {
48    /// Simple field name (e.g., "id", "name")
49    Simple(String),
50
51    /// Complex field with nested selections or directives
52    Complex(IntermediateFragmentFieldDef),
53}
54
55/// Complex fragment field definition with optional alias, directives, and nested fields.
56#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
57pub struct IntermediateFragmentFieldDef {
58    /// Field name (source field in the type)
59    pub name: String,
60
61    /// Output alias (optional, per GraphQL spec §2.13)
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub alias: Option<String>,
64
65    /// Nested field selections (for object fields)
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub fields: Option<Vec<IntermediateFragmentField>>,
68
69    /// Fragment spread (e.g., "...UserFields")
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub spread: Option<String>,
72
73    /// Applied directives (e.g., @skip, @include)
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub directives: Option<Vec<IntermediateAppliedDirective>>,
76}
77
78/// Directive definition in intermediate format.
79///
80/// Directives provide a way to describe alternate runtime execution and type validation.
81/// Per GraphQL spec §2.12, directives can be applied to various locations.
82///
83/// # Example JSON
84///
85/// ```json
86/// {
87///   "name": "auth",
88///   "locations": ["FIELD_DEFINITION", "OBJECT"],
89///   "arguments": [{"name": "role", "type": "String", "nullable": false}],
90///   "description": "Requires authentication with specified role"
91/// }
92/// ```
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94pub struct IntermediateDirective {
95    /// Directive name (without @, e.g., "auth", "deprecated")
96    pub name: String,
97
98    /// Valid locations where this directive can be applied
99    pub locations: Vec<String>,
100
101    /// Directive arguments
102    #[serde(default)]
103    pub arguments: Vec<IntermediateArgument>,
104
105    /// Whether the directive can be applied multiple times
106    #[serde(default)]
107    pub repeatable: bool,
108
109    /// Directive description
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub description: Option<String>,
112}
113
114/// An applied directive instance (used on fields, types, etc.).
115///
116/// # Example JSON
117///
118/// ```json
119/// {
120///   "name": "skip",
121///   "arguments": {"if": true}
122/// }
123/// ```
124#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
125pub struct IntermediateAppliedDirective {
126    /// Directive name (without @)
127    pub name: String,
128
129    /// Directive arguments as key-value pairs
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub arguments: Option<serde_json::Value>,
132}