filesystem_trustfall_adapter/
adapter_impl.rs

1use std::sync::{Arc, OnceLock};
2
3use trustfall::{
4    provider::{
5        resolve_coercion_using_schema, resolve_property_with, AsVertex, ContextIterator,
6        ContextOutcomeIterator, EdgeParameters, ResolveEdgeInfo, ResolveInfo, Typename,
7        VertexIterator,
8    },
9    FieldValue, Schema,
10};
11
12use super::vertex::Vertex;
13
14static SCHEMA: OnceLock<Schema> = OnceLock::new();
15
16#[non_exhaustive]
17#[derive(Debug)]
18pub struct FileSystemAdapter {}
19
20impl Default for FileSystemAdapter {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl FileSystemAdapter {
27    pub const SCHEMA_TEXT: &'static str = include_str!("./schema.graphql");
28
29    pub fn schema() -> &'static Schema {
30        SCHEMA.get_or_init(|| Schema::parse(Self::SCHEMA_TEXT).expect("not a valid schema"))
31    }
32
33    pub fn new() -> Self {
34        Self {}
35    }
36}
37
38impl<'a> trustfall::provider::Adapter<'a> for FileSystemAdapter {
39    type Vertex = Vertex;
40
41    fn resolve_starting_vertices(
42        &self,
43        edge_name: &Arc<str>,
44        parameters: &EdgeParameters,
45        resolve_info: &ResolveInfo,
46    ) -> VertexIterator<'a, Self::Vertex> {
47        match edge_name.as_ref() {
48            "Path" => {
49                let path: &str = parameters
50                    .get("path")
51                    .expect(
52                        "failed to find parameter 'path' when resolving 'Path' starting vertices",
53                    )
54                    .as_str()
55                    .expect(
56                        "unexpected null or other incorrect datatype for Trustfall type 'String!'",
57                    );
58                super::entrypoints::path(path, resolve_info)
59            }
60            _ => {
61                unreachable!(
62                    "attempted to resolve starting vertices for unexpected edge name: {edge_name}"
63                )
64            }
65        }
66    }
67
68    fn resolve_property<V: AsVertex<Self::Vertex> + 'a>(
69        &self,
70        contexts: ContextIterator<'a, V>,
71        type_name: &Arc<str>,
72        property_name: &Arc<str>,
73        resolve_info: &ResolveInfo,
74    ) -> ContextOutcomeIterator<'a, V, FieldValue> {
75        if property_name.as_ref() == "__typename" {
76            return resolve_property_with(contexts, |vertex| vertex.typename().into());
77        }
78        match type_name.as_ref() {
79            "File" => super::properties::resolve_file_property(
80                contexts,
81                property_name.as_ref(),
82                resolve_info,
83            ),
84            "Folder" => super::properties::resolve_folder_property(
85                contexts,
86                property_name.as_ref(),
87                resolve_info,
88            ),
89            "Path" => super::properties::resolve_path_property(
90                contexts,
91                property_name.as_ref(),
92                resolve_info,
93            ),
94            _ => {
95                unreachable!(
96                    "attempted to read property '{property_name}' on unexpected type: {type_name}"
97                )
98            }
99        }
100    }
101
102    fn resolve_neighbors<V: AsVertex<Self::Vertex> + 'a>(
103        &self,
104        contexts: ContextIterator<'a, V>,
105        type_name: &Arc<str>,
106        edge_name: &Arc<str>,
107        parameters: &EdgeParameters,
108        resolve_info: &ResolveEdgeInfo,
109    ) -> ContextOutcomeIterator<'a, V, VertexIterator<'a, Self::Vertex>> {
110        match type_name.as_ref() {
111            "Folder" => super::edges::resolve_folder_edge(
112                contexts,
113                edge_name.as_ref(),
114                parameters,
115                resolve_info,
116            ),
117            _ => {
118                unreachable!(
119                    "attempted to resolve edge '{edge_name}' on unexpected type: {type_name}"
120                )
121            }
122        }
123    }
124
125    fn resolve_coercion<V: AsVertex<Self::Vertex> + 'a>(
126        &self,
127        contexts: ContextIterator<'a, V>,
128        _type_name: &Arc<str>,
129        coerce_to_type: &Arc<str>,
130        _resolve_info: &ResolveInfo,
131    ) -> ContextOutcomeIterator<'a, V, bool> {
132        resolve_coercion_using_schema(contexts, Self::schema(), coerce_to_type.as_ref())
133    }
134}