1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! GraphQL parsing and query processing.
//!
//! This module provides runtime GraphQL query handling:
//! - Query parsing via `graphql-parser` crate
//! - Fragment resolution and expansion
//! - Directive evaluation (@skip, @include)
//! - Fragment cycle detection
//!
//! # Architecture
//!
//! ```text
//! Incoming GraphQL Query
//! │
//! ▼
//! ┌─────────────┐
//! │ Parser │ ← graphql-parser crate
//! └──────┬──────┘
//! │ ParsedQuery
//! ▼
//! ┌─────────────┐
//! │ Fragment │ ← Cycle detection
//! │ Validator │
//! └──────┬──────┘
//! │
//! ▼
//! ┌───────────────────────────────┐
//! │ selection_set │ ← the one routine every entry point
//! │ │ uses: `/graphql`, the multi-root
//! │ Fragment Resolver │ fan-out, `node(id:)`, mutations
//! │ ← spread expansion, with │
//! │ the spread's directives │
//! │ carried onto the fields │
//! │ it contributes (#826) │
//! │ │ │
//! │ ▼ │
//! │ Directive Evaluator │
//! │ ← @skip/@include │
//! └──────────────┬────────────────┘
//! │ Final field list
//! ▼
//! SQL Generation
//! ```
//!
//! Expansion runs first, but it is **not** allowed to discard what it expands:
//! a spread's own `@skip`/`@include` travels onto every field the spread
//! contributes, so the evaluator downstream still sees it. Expansion depends
//! only on the document and is therefore cacheable; directive evaluation needs
//! the request's variables and is not.
//!
//! # Example
//!
//! ```no_run
//! // Requires: fraiseql_core graphql module (internal types).
//! use fraiseql_core::graphql::{parse_query, FragmentResolver, DirectiveEvaluator};
//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
//! let query = r#"
//! fragment UserFields on User { id name }
//! query { users { ...UserFields } }
//! "#;
//!
//! let parsed = parse_query(query)?;
//! let resolver = FragmentResolver::new(&parsed.fragments);
//! let resolved = resolver.resolve_spreads(&parsed.selections)?;
//! # Ok(())
//! # }
//! ```
// ============================================================================
// Module declarations
// ============================================================================
/// GraphQL AST types for query representation.
/// GraphQL query parsing wrapper.
/// The `value_json` encoding shared by every consumer of an inline argument.
/// Fragment resolution and expansion.
/// Directive evaluation (@skip, @include).
/// Fragment cycle detection.
/// The shared selection-resolution routine used by every entry point.
/// Field-existence validation for a resolved selection set (GraphQL § 5.3.1).
/// Query complexity analysis and `DoS` prevention.
/// Field-level RBAC directive (@require_permission).
/// `@defer`: splitting a resolved response into immediate and deferred payloads.
/// Nested `@stream`: splitting an already-resolved list into delivery chunks.
// ============================================================================
// Re-exports for convenient access
// ============================================================================
pub use ;
pub use DeferredPayload;
pub use ;
pub use ;
pub use FragmentGraph;
pub use ;
pub use RequirePermissionDirective;
pub use SelectionError;
pub use ;
pub use ;
// ============================================================================
// Test modules
// ============================================================================