Fix some things
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
6b1e799d6b
commit
e600807376
10 changed files with 421 additions and 81 deletions
|
|
@ -8,6 +8,7 @@ license.workspace = true
|
|||
[dependencies]
|
||||
camino = { version = "1.1.9", features = ["serde", "serde1"] }
|
||||
clap = { version = "4.5.27", features = ["derive"] }
|
||||
filesystem-trustfall-adapter = { version = "0.1.1", path = "../../../trustfall-adapters-zimbopro/filesystem-trustfall-adapter" }
|
||||
futures = "0.3.31"
|
||||
human-panic = "2.0.2"
|
||||
jiff = "0.1.28"
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ use camino::Utf8PathBuf;
|
|||
use clap::Parser;
|
||||
use clap::Subcommand;
|
||||
use clap::ValueHint;
|
||||
use filesystem_trustfall_adapter::FileSystemAdapter;
|
||||
use human_panic::Metadata;
|
||||
use miette::IntoDiagnostic;
|
||||
use parsing::Definition;
|
||||
use parsing::Record;
|
||||
use tracing::info;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
|
@ -64,7 +66,7 @@ async fn main() -> miette::Result<()> {
|
|||
|
||||
let records = parsing::load_records(root_folder, &definitions).await?;
|
||||
|
||||
let schema = trustfall_plaixt::to_schema(&definitions);
|
||||
let (schema, adapter) = get_schema_and_adapter(&definitions, records.clone());
|
||||
|
||||
match args.mode {
|
||||
ArgMode::Query => {
|
||||
|
|
@ -75,13 +77,9 @@ async fn main() -> miette::Result<()> {
|
|||
|
||||
let result = execute_query(
|
||||
&schema,
|
||||
Arc::new(trustfall_plaixt::TrustfallMultiAdapter {
|
||||
plaixt: trustfall_plaixt::PlaixtAdapter {
|
||||
records: records.clone(),
|
||||
},
|
||||
}),
|
||||
Arc::new(adapter),
|
||||
&query,
|
||||
BTreeMap::<Arc<str>, FieldValue>::from([("search".into(), "trust".into())]),
|
||||
BTreeMap::<Arc<str>, FieldValue>::from([]),
|
||||
)
|
||||
.unwrap()
|
||||
.collect::<Vec<_>>();
|
||||
|
|
@ -96,6 +94,20 @@ async fn main() -> miette::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_schema_and_adapter(
|
||||
definitions: &BTreeMap<String, Vec<Definition>>,
|
||||
records: Vec<Record>,
|
||||
) -> (trustfall::Schema, trustfall_plaixt::TrustfallMultiAdapter) {
|
||||
let schema = trustfall_plaixt::to_schema(definitions);
|
||||
let adapter = trustfall_plaixt::TrustfallMultiAdapter {
|
||||
plaixt: trustfall_plaixt::PlaixtAdapter {
|
||||
records: records.clone(),
|
||||
},
|
||||
filesystem: FileSystemAdapter::new(),
|
||||
};
|
||||
(schema, adapter)
|
||||
}
|
||||
|
||||
fn print_records(records: &[Record]) {
|
||||
for record in records {
|
||||
println!("{kind} @ {at} {{", kind = record.kind, at = record.at);
|
||||
|
|
@ -105,3 +117,37 @@ fn print_records(records: &[Record]) {
|
|||
println!("}}")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use camino::Utf8PathBuf;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use trustfall::provider::check_adapter_invariants;
|
||||
|
||||
use crate::get_schema_and_adapter;
|
||||
use crate::parsing;
|
||||
|
||||
#[tokio::test]
|
||||
async fn ensure_adapter_satisfies_invariants() {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::from_default_env())
|
||||
.pretty()
|
||||
.with_test_writer()
|
||||
.init();
|
||||
|
||||
let root_folder = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../examples");
|
||||
|
||||
println!("{root_folder}");
|
||||
let definitions = parsing::load_definitions(&root_folder.join("definitions"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let records = parsing::load_records(&root_folder, &definitions)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (schema, adapter) = get_schema_and_adapter(&definitions, records.clone());
|
||||
|
||||
check_adapter_invariants(&schema, adapter);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ use miette::NamedSource;
|
|||
use owo_colors::OwoColorize;
|
||||
use tokio_stream::wrappers::ReadDirStream;
|
||||
|
||||
use crate::trustfall_plaixt::ADAPTER_SEP;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Record {
|
||||
pub(crate) kind: String,
|
||||
|
|
@ -156,6 +158,7 @@ pub(crate) async fn load_records(
|
|||
#[derive(Debug)]
|
||||
pub enum DefinitionKind {
|
||||
String,
|
||||
Path,
|
||||
OneOf(Vec<String>),
|
||||
}
|
||||
|
||||
|
|
@ -163,6 +166,7 @@ impl DefinitionKind {
|
|||
pub(crate) fn trustfall_kind(&self) -> String {
|
||||
match self {
|
||||
DefinitionKind::String => String::from("String"),
|
||||
DefinitionKind::Path => format!("fs{ADAPTER_SEP}Path"),
|
||||
DefinitionKind::OneOf(_vecs) => String::from("String"),
|
||||
}
|
||||
}
|
||||
|
|
@ -173,6 +177,10 @@ impl DefinitionKind {
|
|||
.is_string()
|
||||
.then_some(())
|
||||
.ok_or("Expected a string here".to_string()),
|
||||
DefinitionKind::Path => val
|
||||
.is_string()
|
||||
.then_some(())
|
||||
.ok_or("Expected a path encoded as a string here".to_string()),
|
||||
DefinitionKind::OneOf(options) => val
|
||||
.as_string()
|
||||
.is_some_and(|val| options.iter().any(|o| o == val))
|
||||
|
|
@ -187,6 +195,7 @@ impl TryFrom<&str> for DefinitionKind {
|
|||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
match value.to_ascii_lowercase().as_str() {
|
||||
"string" => Ok(DefinitionKind::String),
|
||||
"path" => Ok(DefinitionKind::Path),
|
||||
other => miette::bail!("Did not recognize valid field kind: \"{other}\""),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use trustfall::Schema;
|
|||
use crate::parsing::Definition;
|
||||
use crate::parsing::Record;
|
||||
|
||||
const ADAPTER_SEP: &str = "__";
|
||||
pub(crate) const ADAPTER_SEP: &str = "__";
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct StartingVertex {
|
||||
|
|
@ -155,12 +155,29 @@ pub(crate) fn to_schema(definitions: &BTreeMap<String, Vec<Definition>>) -> Sche
|
|||
{}
|
||||
type RootSchemaQuery {{
|
||||
{roots}
|
||||
fs{ADAPTER_SEP}Path(path: String!): fs{ADAPTER_SEP}Path!,
|
||||
}}
|
||||
interface Record {{
|
||||
at: String!,
|
||||
kind: String!,
|
||||
}}
|
||||
|
||||
interface fs{ADAPTER_SEP}Path {{
|
||||
path: String!
|
||||
}}
|
||||
|
||||
type fs{ADAPTER_SEP}Folder implements fs{ADAPTER_SEP}Path {{
|
||||
path: String!
|
||||
children: [fs{ADAPTER_SEP}Path!]
|
||||
}}
|
||||
|
||||
type fs{ADAPTER_SEP}File implements fs{ADAPTER_SEP}Path {{
|
||||
path: String!
|
||||
size: Int!
|
||||
extension: String!
|
||||
Hash: String!
|
||||
}}
|
||||
|
||||
{types}
|
||||
"#,
|
||||
Schema::ALL_DIRECTIVE_DEFINITIONS,
|
||||
|
|
@ -179,11 +196,23 @@ pub(crate) fn to_schema(definitions: &BTreeMap<String, Vec<Definition>>) -> Sche
|
|||
|
||||
pub struct TrustfallMultiAdapter {
|
||||
pub plaixt: PlaixtAdapter,
|
||||
pub filesystem: filesystem_trustfall_adapter::FileSystemAdapter,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TrustfallMultiVertex {
|
||||
Plaixt(PlaixtVertex),
|
||||
Filesystem(filesystem_trustfall_adapter::vertex::Vertex),
|
||||
}
|
||||
|
||||
impl AsVertex<filesystem_trustfall_adapter::vertex::Vertex> for TrustfallMultiVertex {
|
||||
fn as_vertex(&self) -> Option<&filesystem_trustfall_adapter::vertex::Vertex> {
|
||||
self.as_filesystem()
|
||||
}
|
||||
|
||||
fn into_vertex(self) -> Option<filesystem_trustfall_adapter::vertex::Vertex> {
|
||||
self.as_filesystem().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsVertex<PlaixtVertex> for TrustfallMultiVertex {
|
||||
|
|
@ -204,6 +233,20 @@ impl TrustfallMultiVertex {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_filesystem(
|
||||
&self,
|
||||
) -> Option<
|
||||
&<filesystem_trustfall_adapter::FileSystemAdapter as trustfall::provider::Adapter<
|
||||
'static,
|
||||
>>::Vertex,
|
||||
> {
|
||||
if let Self::Filesystem(v) = self {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
||||
|
|
@ -217,7 +260,11 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
) -> trustfall::provider::VertexIterator<'v, Self::Vertex> {
|
||||
let (adapter_name, edge_name) = edge_name.split_once(ADAPTER_SEP).unwrap();
|
||||
|
||||
trace!(?adapter_name, ?edge_name, "Got start vertex");
|
||||
trace!(
|
||||
?adapter_name,
|
||||
?edge_name,
|
||||
"resolving top-level starting vertex"
|
||||
);
|
||||
|
||||
match adapter_name {
|
||||
"Plaixt" => {
|
||||
|
|
@ -229,6 +276,18 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
|
||||
Box::new(iter.map(TrustfallMultiVertex::Plaixt))
|
||||
}
|
||||
"fs" => {
|
||||
let iter = self.filesystem.resolve_starting_vertices(
|
||||
&Arc::from(edge_name),
|
||||
parameters,
|
||||
resolve_info,
|
||||
);
|
||||
|
||||
Box::new(
|
||||
iter.inspect(|v| trace!(?v, "Got vertex"))
|
||||
.map(TrustfallMultiVertex::Filesystem),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -243,7 +302,10 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
where
|
||||
V: trustfall::provider::AsVertex<Self::Vertex> + 'v,
|
||||
{
|
||||
let (adapter_name, type_name) = type_name.split_once(ADAPTER_SEP).unwrap();
|
||||
trace!(?type_name, ?property_name, "resolving top-level property");
|
||||
let (adapter_name, type_name) = type_name
|
||||
.split_once(ADAPTER_SEP)
|
||||
.unwrap_or(("Plaixt", type_name));
|
||||
|
||||
match adapter_name {
|
||||
"Plaixt" => {
|
||||
|
|
@ -268,6 +330,29 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
.map(|((_ctx, name), og_ctx)| (og_ctx, name)),
|
||||
)
|
||||
}
|
||||
"fs" => {
|
||||
let contexts = contexts.collect::<Vec<_>>();
|
||||
|
||||
let properties = self.filesystem.resolve_property(
|
||||
Box::new(
|
||||
contexts
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|v| v.flat_map(&mut |v: V| v.into_vertex()))
|
||||
.inspect(|v| trace!(?v, "Got vertex")),
|
||||
),
|
||||
&Arc::from(type_name),
|
||||
property_name,
|
||||
resolve_info,
|
||||
);
|
||||
|
||||
Box::new(
|
||||
properties
|
||||
.into_iter()
|
||||
.zip(contexts)
|
||||
.map(|((_ctx, name), og_ctx)| (og_ctx, name)),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -284,6 +369,7 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
V,
|
||||
trustfall::provider::VertexIterator<'v, Self::Vertex>,
|
||||
> {
|
||||
trace!(?type_name, ?edge_name, "Resolving top-level neighbor");
|
||||
let (adapter_name, type_name) = type_name.split_once(ADAPTER_SEP).unwrap();
|
||||
|
||||
match adapter_name {
|
||||
|
|
@ -315,6 +401,37 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
}),
|
||||
)
|
||||
}
|
||||
"fs" => {
|
||||
let contexts = contexts.collect::<Vec<_>>();
|
||||
|
||||
let properties = self.filesystem.resolve_neighbors(
|
||||
Box::new(
|
||||
contexts
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|v| v.flat_map(&mut |v: V| v.into_vertex())),
|
||||
),
|
||||
&Arc::from(type_name),
|
||||
edge_name,
|
||||
parameters,
|
||||
resolve_info,
|
||||
);
|
||||
|
||||
Box::new(
|
||||
properties
|
||||
.into_iter()
|
||||
.zip(contexts)
|
||||
.map(|((_ctx, vals), og_ctx)| {
|
||||
(
|
||||
og_ctx,
|
||||
Box::new(
|
||||
vals.inspect(|v| trace!(?v, "Got vertex"))
|
||||
.map(TrustfallMultiVertex::Filesystem),
|
||||
) as Box<_>,
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -326,7 +443,7 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
coerce_to_type: &Arc<str>,
|
||||
resolve_info: &trustfall::provider::ResolveInfo,
|
||||
) -> trustfall::provider::ContextOutcomeIterator<'v, V, bool> {
|
||||
trace!(?type_name, ?coerce_to_type, "Trying to coerce");
|
||||
trace!(?type_name, ?coerce_to_type, "Top-level coerce");
|
||||
let (adapter_name, coerce_to_type) = coerce_to_type.split_once(ADAPTER_SEP).unwrap();
|
||||
|
||||
match adapter_name {
|
||||
|
|
@ -352,6 +469,30 @@ impl<'v> Adapter<'v> for TrustfallMultiAdapter {
|
|||
.map(|((_ctx, val), og_ctx)| (og_ctx, val)),
|
||||
)
|
||||
}
|
||||
"fs" => {
|
||||
let contexts = contexts.collect::<Vec<_>>();
|
||||
|
||||
let properties = self.filesystem.resolve_coercion(
|
||||
Box::new(
|
||||
contexts
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|v| v.flat_map(&mut |v: V| v.into_vertex())),
|
||||
),
|
||||
type_name,
|
||||
&Arc::from(coerce_to_type),
|
||||
resolve_info,
|
||||
);
|
||||
|
||||
let type_name = type_name.clone();
|
||||
let coerce_to_type = coerce_to_type.to_string();
|
||||
Box::new(properties.into_iter().zip(contexts).map(
|
||||
move |((_ctx, allowed), og_ctx)| {
|
||||
trace!(?allowed, ?type_name, ?coerce_to_type, "Allowed coercion?");
|
||||
(og_ctx, allowed)
|
||||
},
|
||||
))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -454,7 +595,7 @@ impl<'a> Adapter<'a> for PlaixtAdapter {
|
|||
fn resolve_neighbors<V: trustfall::provider::AsVertex<Self::Vertex> + 'a>(
|
||||
&self,
|
||||
contexts: trustfall::provider::ContextIterator<'a, V>,
|
||||
_type_name: &Arc<str>,
|
||||
type_name: &Arc<str>,
|
||||
edge_name: &Arc<str>,
|
||||
_parameters: &trustfall::provider::EdgeParameters,
|
||||
_resolve_info: &trustfall::provider::ResolveEdgeInfo,
|
||||
|
|
@ -463,6 +604,7 @@ impl<'a> Adapter<'a> for PlaixtAdapter {
|
|||
V,
|
||||
trustfall::provider::VertexIterator<'a, Self::Vertex>,
|
||||
> {
|
||||
trace!(?type_name, ?edge_name, "Resolving neighbors");
|
||||
match edge_name.as_ref() {
|
||||
"fields" => resolve_neighbors_with(contexts, |c| {
|
||||
Box::new(
|
||||
|
|
@ -474,7 +616,8 @@ impl<'a> Adapter<'a> for PlaixtAdapter {
|
|||
.into_iter(),
|
||||
)
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
_ => resolve_neighbors_with(contexts, |c| todo!()),
|
||||
_ => unreachable!("Could not resolve {edge_name}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue